{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "2e32c2ca-9795-4aed-9710-43b594fe992d",
   "metadata": {},
   "source": [
    "# 快速搭建 RAG Demo"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f945cd11-b7a2-4e78-9f0f-f33051b810bc",
   "metadata": {},
   "source": [
    "1. 调用 DeepSeek R1"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "479d002d-eb23-450f-bd56-80552b97507c",
   "metadata": {},
   "source": [
    "在该部分，你需要从任一 LLM 平台获取一个 DeepSeek R1 调用的接口，并参考平台的代码示例完成调用代码，此处仅给出几个推荐平台链接：\n",
    "- DeepSeek：https://platform.deepseek.com/usage\n",
    "- 火山：https://www.volcengine.com/docs/82379/\n",
    "- 文心千帆：https://cloud.baidu.com/product-s/qianfan_home"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "808b2225-4d40-4c7b-9fa0-1b0a0878564b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple\n",
      "Requirement already satisfied: openai in /opt/conda/lib/python3.11/site-packages (1.51.2)\n",
      "Requirement already satisfied: anyio<5,>=3.5.0 in /opt/conda/lib/python3.11/site-packages (from openai) (4.6.0)\n",
      "Requirement already satisfied: distro<2,>=1.7.0 in /opt/conda/lib/python3.11/site-packages (from openai) (1.9.0)\n",
      "Requirement already satisfied: httpx<1,>=0.23.0 in /opt/conda/lib/python3.11/site-packages (from openai) (0.27.2)\n",
      "Requirement already satisfied: jiter<1,>=0.4.0 in /opt/conda/lib/python3.11/site-packages (from openai) (0.6.1)\n",
      "Requirement already satisfied: pydantic<3,>=1.9.0 in /opt/conda/lib/python3.11/site-packages (from openai) (2.9.2)\n",
      "Requirement already satisfied: sniffio in /opt/conda/lib/python3.11/site-packages (from openai) (1.3.1)\n",
      "Requirement already satisfied: tqdm>4 in /opt/conda/lib/python3.11/site-packages (from openai) (4.66.4)\n",
      "Requirement already satisfied: typing-extensions<5,>=4.11 in /opt/conda/lib/python3.11/site-packages (from openai) (4.12.2)\n",
      "Requirement already satisfied: idna>=2.8 in /opt/conda/lib/python3.11/site-packages (from anyio<5,>=3.5.0->openai) (3.7)\n",
      "Requirement already satisfied: certifi in /opt/conda/lib/python3.11/site-packages (from httpx<1,>=0.23.0->openai) (2024.8.30)\n",
      "Requirement already satisfied: httpcore==1.* in /opt/conda/lib/python3.11/site-packages (from httpx<1,>=0.23.0->openai) (1.0.6)\n",
      "Requirement already satisfied: h11<0.15,>=0.13 in /opt/conda/lib/python3.11/site-packages (from httpcore==1.*->httpx<1,>=0.23.0->openai) (0.14.0)\n",
      "Requirement already satisfied: annotated-types>=0.6.0 in /opt/conda/lib/python3.11/site-packages (from pydantic<3,>=1.9.0->openai) (0.7.0)\n",
      "Requirement already satisfied: pydantic-core==2.23.4 in /opt/conda/lib/python3.11/site-packages (from pydantic<3,>=1.9.0->openai) (2.23.4)\n",
      "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager, possibly rendering your system unusable.It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv. Use the --root-user-action option if you know what you are doing and want to suppress this warning.\u001b[0m\u001b[33m\n",
      "\u001b[0m"
     ]
    }
   ],
   "source": [
    "# 安装 openai\n",
    "!pip install openai"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "0f2ec0ce",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'此处可以测试调用 LLM API 的代码'"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "\n",
    "'''此处可以测试调用 LLM API 的代码'''\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "1d3a4cfa-ac4e-4fa3-9a42-731f103c29a0",
   "metadata": {
    "collapsed": true,
    "jupyter": {
     "outputs_hidden": true
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple\n",
      "Collecting langchain==0.3.0\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/8a/db/38de43dae7e23f8de1d92e9a02c2d7cf8b604c25f76a65da3e6959233b78/langchain-0.3.0-py3-none-any.whl (1.0 MB)\n",
      "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.0/1.0 MB\u001b[0m \u001b[31m12.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[?25hRequirement already satisfied: PyYAML>=5.3 in /opt/conda/lib/python3.11/site-packages (from langchain==0.3.0) (6.0.2)\n",
      "Collecting SQLAlchemy<3,>=1.4 (from langchain==0.3.0)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/ff/0a/46f3171f564a19a1daf6e7e0e6c8afc6ecd792f947c6de435519d4d16af3/sqlalchemy-2.0.39-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (3.2 MB)\n",
      "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m3.2/3.2 MB\u001b[0m \u001b[31m34.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[?25hRequirement already satisfied: aiohttp<4.0.0,>=3.8.3 in /opt/conda/lib/python3.11/site-packages (from langchain==0.3.0) (3.10.9)\n",
      "Collecting langchain-core<0.4.0,>=0.3.0 (from langchain==0.3.0)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/66/06/4ddafa246b4f1b2017918237b681e884fd02d34b0cb3dcc802105b53872d/langchain_core-0.3.48-py3-none-any.whl (418 kB)\n",
      "Collecting langchain-text-splitters<0.4.0,>=0.3.0 (from langchain==0.3.0)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/d3/85/b7a34b6d34bcc89a2252f5ffea30b94077ba3d7adf72e31b9e04e68c901a/langchain_text_splitters-0.3.7-py3-none-any.whl (32 kB)\n",
      "Collecting langsmith<0.2.0,>=0.1.17 (from langchain==0.3.0)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/de/f0/63b06b99b730b9954f8709f6f7d9b8d076fa0a973e472efe278089bde42b/langsmith-0.1.147-py3-none-any.whl (311 kB)\n",
      "Requirement already satisfied: numpy<2,>=1 in /opt/conda/lib/python3.11/site-packages (from langchain==0.3.0) (1.24.3)\n",
      "Requirement already satisfied: pydantic<3.0.0,>=2.7.4 in /opt/conda/lib/python3.11/site-packages (from langchain==0.3.0) (2.9.2)\n",
      "Requirement already satisfied: requests<3,>=2 in /opt/conda/lib/python3.11/site-packages (from langchain==0.3.0) (2.32.3)\n",
      "Collecting tenacity!=8.4.0,<9.0.0,>=8.1.0 (from langchain==0.3.0)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/d2/3f/8ba87d9e287b9d385a02a7114ddcef61b26f86411e121c9003eb509a1773/tenacity-8.5.0-py3-none-any.whl (28 kB)\n",
      "Requirement already satisfied: aiohappyeyeballs>=2.3.0 in /opt/conda/lib/python3.11/site-packages (from aiohttp<4.0.0,>=3.8.3->langchain==0.3.0) (2.4.3)\n",
      "Requirement already satisfied: aiosignal>=1.1.2 in /opt/conda/lib/python3.11/site-packages (from aiohttp<4.0.0,>=3.8.3->langchain==0.3.0) (1.3.1)\n",
      "Requirement already satisfied: attrs>=17.3.0 in /opt/conda/lib/python3.11/site-packages (from aiohttp<4.0.0,>=3.8.3->langchain==0.3.0) (24.2.0)\n",
      "Requirement already satisfied: frozenlist>=1.1.1 in /opt/conda/lib/python3.11/site-packages (from aiohttp<4.0.0,>=3.8.3->langchain==0.3.0) (1.4.1)\n",
      "Requirement already satisfied: multidict<7.0,>=4.5 in /opt/conda/lib/python3.11/site-packages (from aiohttp<4.0.0,>=3.8.3->langchain==0.3.0) (6.1.0)\n",
      "Requirement already satisfied: yarl<2.0,>=1.12.0 in /opt/conda/lib/python3.11/site-packages (from aiohttp<4.0.0,>=3.8.3->langchain==0.3.0) (1.14.0)\n",
      "Requirement already satisfied: jsonpatch<2.0,>=1.33 in /opt/conda/lib/python3.11/site-packages (from langchain-core<0.4.0,>=0.3.0->langchain==0.3.0) (1.33)\n",
      "Requirement already satisfied: packaging<25,>=23.2 in /opt/conda/lib/python3.11/site-packages (from langchain-core<0.4.0,>=0.3.0->langchain==0.3.0) (24.1)\n",
      "Requirement already satisfied: typing-extensions>=4.7 in /opt/conda/lib/python3.11/site-packages (from langchain-core<0.4.0,>=0.3.0->langchain==0.3.0) (4.12.2)\n",
      "Requirement already satisfied: httpx<1,>=0.23.0 in /opt/conda/lib/python3.11/site-packages (from langsmith<0.2.0,>=0.1.17->langchain==0.3.0) (0.27.2)\n",
      "Collecting orjson<4.0.0,>=3.9.14 (from langsmith<0.2.0,>=0.1.17->langchain==0.3.0)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/92/18/5b1e1e995bffad49dc4311a0bdfd874bc6f135fd20f0e1f671adc2c9910e/orjson-3.10.16-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (132 kB)\n",
      "Collecting requests-toolbelt<2.0.0,>=1.0.0 (from langsmith<0.2.0,>=0.1.17->langchain==0.3.0)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/3f/51/d4db610ef29373b879047326cbf6fa98b6c1969d6f6dc423279de2b1be2c/requests_toolbelt-1.0.0-py2.py3-none-any.whl (54 kB)\n",
      "Requirement already satisfied: annotated-types>=0.6.0 in /opt/conda/lib/python3.11/site-packages (from pydantic<3.0.0,>=2.7.4->langchain==0.3.0) (0.7.0)\n",
      "Requirement already satisfied: pydantic-core==2.23.4 in /opt/conda/lib/python3.11/site-packages (from pydantic<3.0.0,>=2.7.4->langchain==0.3.0) (2.23.4)\n",
      "Requirement already satisfied: charset-normalizer<4,>=2 in /opt/conda/lib/python3.11/site-packages (from requests<3,>=2->langchain==0.3.0) (3.3.2)\n",
      "Requirement already satisfied: idna<4,>=2.5 in /opt/conda/lib/python3.11/site-packages (from requests<3,>=2->langchain==0.3.0) (3.7)\n",
      "Requirement already satisfied: urllib3<3,>=1.21.1 in /opt/conda/lib/python3.11/site-packages (from requests<3,>=2->langchain==0.3.0) (2.2.2)\n",
      "Requirement already satisfied: certifi>=2017.4.17 in /opt/conda/lib/python3.11/site-packages (from requests<3,>=2->langchain==0.3.0) (2024.8.30)\n",
      "Collecting greenlet!=0.4.17 (from SQLAlchemy<3,>=1.4->langchain==0.3.0)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/f7/4b/1c9695aa24f808e156c8f4813f685d975ca73c000c2a5056c514c64980f6/greenlet-3.1.1-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl (602 kB)\n",
      "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m602.4/602.4 kB\u001b[0m \u001b[31m60.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[?25hRequirement already satisfied: anyio in /opt/conda/lib/python3.11/site-packages (from httpx<1,>=0.23.0->langsmith<0.2.0,>=0.1.17->langchain==0.3.0) (4.6.0)\n",
      "Requirement already satisfied: httpcore==1.* in /opt/conda/lib/python3.11/site-packages (from httpx<1,>=0.23.0->langsmith<0.2.0,>=0.1.17->langchain==0.3.0) (1.0.6)\n",
      "Requirement already satisfied: sniffio in /opt/conda/lib/python3.11/site-packages (from httpx<1,>=0.23.0->langsmith<0.2.0,>=0.1.17->langchain==0.3.0) (1.3.1)\n",
      "Requirement already satisfied: h11<0.15,>=0.13 in /opt/conda/lib/python3.11/site-packages (from httpcore==1.*->httpx<1,>=0.23.0->langsmith<0.2.0,>=0.1.17->langchain==0.3.0) (0.14.0)\n",
      "Requirement already satisfied: jsonpointer>=1.9 in /opt/conda/lib/python3.11/site-packages (from jsonpatch<2.0,>=1.33->langchain-core<0.4.0,>=0.3.0->langchain==0.3.0) (2.1)\n",
      "Requirement already satisfied: propcache>=0.2.0 in /opt/conda/lib/python3.11/site-packages (from yarl<2.0,>=1.12.0->aiohttp<4.0.0,>=3.8.3->langchain==0.3.0) (0.2.0)\n",
      "Installing collected packages: tenacity, orjson, greenlet, SQLAlchemy, requests-toolbelt, langsmith, langchain-core, langchain-text-splitters, langchain\n",
      "Successfully installed SQLAlchemy-2.0.39 greenlet-3.1.1 langchain-0.3.0 langchain-core-0.3.48 langchain-text-splitters-0.3.7 langsmith-0.1.147 orjson-3.10.16 requests-toolbelt-1.0.0 tenacity-8.5.0\n",
      "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager, possibly rendering your system unusable.It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv. Use the --root-user-action option if you know what you are doing and want to suppress this warning.\u001b[0m\u001b[33m\n",
      "\u001b[0mLooking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple\n",
      "Collecting langchain-community==0.3.0\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/07/3d/a30549f1c5fa023b833a81eab43f99d6f603bed5ecfaef175f53e7166dbf/langchain_community-0.3.0-py3-none-any.whl (2.3 MB)\n",
      "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m2.3/2.3 MB\u001b[0m \u001b[31m9.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0ma \u001b[36m0:00:01\u001b[0m\n",
      "\u001b[?25hRequirement already satisfied: PyYAML>=5.3 in /opt/conda/lib/python3.11/site-packages (from langchain-community==0.3.0) (6.0.2)\n",
      "Requirement already satisfied: SQLAlchemy<3,>=1.4 in /opt/conda/lib/python3.11/site-packages (from langchain-community==0.3.0) (2.0.39)\n",
      "Requirement already satisfied: aiohttp<4.0.0,>=3.8.3 in /opt/conda/lib/python3.11/site-packages (from langchain-community==0.3.0) (3.10.9)\n",
      "Collecting dataclasses-json<0.7,>=0.5.7 (from langchain-community==0.3.0)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/c3/be/d0d44e092656fe7a06b55e6103cbce807cdbdee17884a5367c68c9860853/dataclasses_json-0.6.7-py3-none-any.whl (28 kB)\n",
      "Requirement already satisfied: langchain<0.4.0,>=0.3.0 in /opt/conda/lib/python3.11/site-packages (from langchain-community==0.3.0) (0.3.0)\n",
      "Requirement already satisfied: langchain-core<0.4.0,>=0.3.0 in /opt/conda/lib/python3.11/site-packages (from langchain-community==0.3.0) (0.3.48)\n",
      "Requirement already satisfied: langsmith<0.2.0,>=0.1.112 in /opt/conda/lib/python3.11/site-packages (from langchain-community==0.3.0) (0.1.147)\n",
      "Requirement already satisfied: numpy<2,>=1 in /opt/conda/lib/python3.11/site-packages (from langchain-community==0.3.0) (1.24.3)\n",
      "Collecting pydantic-settings<3.0.0,>=2.4.0 (from langchain-community==0.3.0)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/0b/53/a64f03044927dc47aafe029c42a5b7aabc38dfb813475e0e1bf71c4a59d0/pydantic_settings-2.8.1-py3-none-any.whl (30 kB)\n",
      "Requirement already satisfied: requests<3,>=2 in /opt/conda/lib/python3.11/site-packages (from langchain-community==0.3.0) (2.32.3)\n",
      "Requirement already satisfied: tenacity!=8.4.0,<9.0.0,>=8.1.0 in /opt/conda/lib/python3.11/site-packages (from langchain-community==0.3.0) (8.5.0)\n",
      "Requirement already satisfied: aiohappyeyeballs>=2.3.0 in /opt/conda/lib/python3.11/site-packages (from aiohttp<4.0.0,>=3.8.3->langchain-community==0.3.0) (2.4.3)\n",
      "Requirement already satisfied: aiosignal>=1.1.2 in /opt/conda/lib/python3.11/site-packages (from aiohttp<4.0.0,>=3.8.3->langchain-community==0.3.0) (1.3.1)\n",
      "Requirement already satisfied: attrs>=17.3.0 in /opt/conda/lib/python3.11/site-packages (from aiohttp<4.0.0,>=3.8.3->langchain-community==0.3.0) (24.2.0)\n",
      "Requirement already satisfied: frozenlist>=1.1.1 in /opt/conda/lib/python3.11/site-packages (from aiohttp<4.0.0,>=3.8.3->langchain-community==0.3.0) (1.4.1)\n",
      "Requirement already satisfied: multidict<7.0,>=4.5 in /opt/conda/lib/python3.11/site-packages (from aiohttp<4.0.0,>=3.8.3->langchain-community==0.3.0) (6.1.0)\n",
      "Requirement already satisfied: yarl<2.0,>=1.12.0 in /opt/conda/lib/python3.11/site-packages (from aiohttp<4.0.0,>=3.8.3->langchain-community==0.3.0) (1.14.0)\n",
      "Collecting marshmallow<4.0.0,>=3.18.0 (from dataclasses-json<0.7,>=0.5.7->langchain-community==0.3.0)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/34/75/51952c7b2d3873b44a0028b1bd26a25078c18f92f256608e8d1dc61b39fd/marshmallow-3.26.1-py3-none-any.whl (50 kB)\n",
      "Collecting typing-inspect<1,>=0.4.0 (from dataclasses-json<0.7,>=0.5.7->langchain-community==0.3.0)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/65/f3/107a22063bf27bdccf2024833d3445f4eea42b2e598abfbd46f6a63b6cb0/typing_inspect-0.9.0-py3-none-any.whl (8.8 kB)\n",
      "Requirement already satisfied: langchain-text-splitters<0.4.0,>=0.3.0 in /opt/conda/lib/python3.11/site-packages (from langchain<0.4.0,>=0.3.0->langchain-community==0.3.0) (0.3.7)\n",
      "Requirement already satisfied: pydantic<3.0.0,>=2.7.4 in /opt/conda/lib/python3.11/site-packages (from langchain<0.4.0,>=0.3.0->langchain-community==0.3.0) (2.9.2)\n",
      "Requirement already satisfied: jsonpatch<2.0,>=1.33 in /opt/conda/lib/python3.11/site-packages (from langchain-core<0.4.0,>=0.3.0->langchain-community==0.3.0) (1.33)\n",
      "Requirement already satisfied: packaging<25,>=23.2 in /opt/conda/lib/python3.11/site-packages (from langchain-core<0.4.0,>=0.3.0->langchain-community==0.3.0) (24.1)\n",
      "Requirement already satisfied: typing-extensions>=4.7 in /opt/conda/lib/python3.11/site-packages (from langchain-core<0.4.0,>=0.3.0->langchain-community==0.3.0) (4.12.2)\n",
      "Requirement already satisfied: httpx<1,>=0.23.0 in /opt/conda/lib/python3.11/site-packages (from langsmith<0.2.0,>=0.1.112->langchain-community==0.3.0) (0.27.2)\n",
      "Requirement already satisfied: orjson<4.0.0,>=3.9.14 in /opt/conda/lib/python3.11/site-packages (from langsmith<0.2.0,>=0.1.112->langchain-community==0.3.0) (3.10.16)\n",
      "Requirement already satisfied: requests-toolbelt<2.0.0,>=1.0.0 in /opt/conda/lib/python3.11/site-packages (from langsmith<0.2.0,>=0.1.112->langchain-community==0.3.0) (1.0.0)\n",
      "Requirement already satisfied: python-dotenv>=0.21.0 in /opt/conda/lib/python3.11/site-packages (from pydantic-settings<3.0.0,>=2.4.0->langchain-community==0.3.0) (1.0.1)\n",
      "Requirement already satisfied: charset-normalizer<4,>=2 in /opt/conda/lib/python3.11/site-packages (from requests<3,>=2->langchain-community==0.3.0) (3.3.2)\n",
      "Requirement already satisfied: idna<4,>=2.5 in /opt/conda/lib/python3.11/site-packages (from requests<3,>=2->langchain-community==0.3.0) (3.7)\n",
      "Requirement already satisfied: urllib3<3,>=1.21.1 in /opt/conda/lib/python3.11/site-packages (from requests<3,>=2->langchain-community==0.3.0) (2.2.2)\n",
      "Requirement already satisfied: certifi>=2017.4.17 in /opt/conda/lib/python3.11/site-packages (from requests<3,>=2->langchain-community==0.3.0) (2024.8.30)\n",
      "Requirement already satisfied: greenlet!=0.4.17 in /opt/conda/lib/python3.11/site-packages (from SQLAlchemy<3,>=1.4->langchain-community==0.3.0) (3.1.1)\n",
      "Requirement already satisfied: anyio in /opt/conda/lib/python3.11/site-packages (from httpx<1,>=0.23.0->langsmith<0.2.0,>=0.1.112->langchain-community==0.3.0) (4.6.0)\n",
      "Requirement already satisfied: httpcore==1.* in /opt/conda/lib/python3.11/site-packages (from httpx<1,>=0.23.0->langsmith<0.2.0,>=0.1.112->langchain-community==0.3.0) (1.0.6)\n",
      "Requirement already satisfied: sniffio in /opt/conda/lib/python3.11/site-packages (from httpx<1,>=0.23.0->langsmith<0.2.0,>=0.1.112->langchain-community==0.3.0) (1.3.1)\n",
      "Requirement already satisfied: h11<0.15,>=0.13 in /opt/conda/lib/python3.11/site-packages (from httpcore==1.*->httpx<1,>=0.23.0->langsmith<0.2.0,>=0.1.112->langchain-community==0.3.0) (0.14.0)\n",
      "Requirement already satisfied: jsonpointer>=1.9 in /opt/conda/lib/python3.11/site-packages (from jsonpatch<2.0,>=1.33->langchain-core<0.4.0,>=0.3.0->langchain-community==0.3.0) (2.1)\n",
      "Requirement already satisfied: annotated-types>=0.6.0 in /opt/conda/lib/python3.11/site-packages (from pydantic<3.0.0,>=2.7.4->langchain<0.4.0,>=0.3.0->langchain-community==0.3.0) (0.7.0)\n",
      "Requirement already satisfied: pydantic-core==2.23.4 in /opt/conda/lib/python3.11/site-packages (from pydantic<3.0.0,>=2.7.4->langchain<0.4.0,>=0.3.0->langchain-community==0.3.0) (2.23.4)\n",
      "Collecting mypy-extensions>=0.3.0 (from typing-inspect<1,>=0.4.0->dataclasses-json<0.7,>=0.5.7->langchain-community==0.3.0)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/2a/e2/5d3f6ada4297caebe1a2add3b126fe800c96f56dbe5d1988a2cbe0b267aa/mypy_extensions-1.0.0-py3-none-any.whl (4.7 kB)\n",
      "Requirement already satisfied: propcache>=0.2.0 in /opt/conda/lib/python3.11/site-packages (from yarl<2.0,>=1.12.0->aiohttp<4.0.0,>=3.8.3->langchain-community==0.3.0) (0.2.0)\n",
      "Installing collected packages: mypy-extensions, marshmallow, typing-inspect, pydantic-settings, dataclasses-json, langchain-community\n",
      "Successfully installed dataclasses-json-0.6.7 langchain-community-0.3.0 marshmallow-3.26.1 mypy-extensions-1.0.0 pydantic-settings-2.8.1 typing-inspect-0.9.0\n",
      "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager, possibly rendering your system unusable.It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv. Use the --root-user-action option if you know what you are doing and want to suppress this warning.\u001b[0m\u001b[33m\n",
      "\u001b[0mLooking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple\n",
      "Collecting langchain-text-splitters==0.3.0\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/da/6a/d1303b722a3fa7a0a8c2f8f5307e42f0bdbded46d99cca436f3db0df5294/langchain_text_splitters-0.3.0-py3-none-any.whl (25 kB)\n",
      "Requirement already satisfied: langchain-core<0.4.0,>=0.3.0 in /opt/conda/lib/python3.11/site-packages (from langchain-text-splitters==0.3.0) (0.3.48)\n",
      "Requirement already satisfied: langsmith<0.4,>=0.1.125 in /opt/conda/lib/python3.11/site-packages (from langchain-core<0.4.0,>=0.3.0->langchain-text-splitters==0.3.0) (0.1.147)\n",
      "Requirement already satisfied: tenacity!=8.4.0,<10.0.0,>=8.1.0 in /opt/conda/lib/python3.11/site-packages (from langchain-core<0.4.0,>=0.3.0->langchain-text-splitters==0.3.0) (8.5.0)\n",
      "Requirement already satisfied: jsonpatch<2.0,>=1.33 in /opt/conda/lib/python3.11/site-packages (from langchain-core<0.4.0,>=0.3.0->langchain-text-splitters==0.3.0) (1.33)\n",
      "Requirement already satisfied: PyYAML>=5.3 in /opt/conda/lib/python3.11/site-packages (from langchain-core<0.4.0,>=0.3.0->langchain-text-splitters==0.3.0) (6.0.2)\n",
      "Requirement already satisfied: packaging<25,>=23.2 in /opt/conda/lib/python3.11/site-packages (from langchain-core<0.4.0,>=0.3.0->langchain-text-splitters==0.3.0) (24.1)\n",
      "Requirement already satisfied: typing-extensions>=4.7 in /opt/conda/lib/python3.11/site-packages (from langchain-core<0.4.0,>=0.3.0->langchain-text-splitters==0.3.0) (4.12.2)\n",
      "Requirement already satisfied: pydantic<3.0.0,>=2.5.2 in /opt/conda/lib/python3.11/site-packages (from langchain-core<0.4.0,>=0.3.0->langchain-text-splitters==0.3.0) (2.9.2)\n",
      "Requirement already satisfied: jsonpointer>=1.9 in /opt/conda/lib/python3.11/site-packages (from jsonpatch<2.0,>=1.33->langchain-core<0.4.0,>=0.3.0->langchain-text-splitters==0.3.0) (2.1)\n",
      "Requirement already satisfied: httpx<1,>=0.23.0 in /opt/conda/lib/python3.11/site-packages (from langsmith<0.4,>=0.1.125->langchain-core<0.4.0,>=0.3.0->langchain-text-splitters==0.3.0) (0.27.2)\n",
      "Requirement already satisfied: orjson<4.0.0,>=3.9.14 in /opt/conda/lib/python3.11/site-packages (from langsmith<0.4,>=0.1.125->langchain-core<0.4.0,>=0.3.0->langchain-text-splitters==0.3.0) (3.10.16)\n",
      "Requirement already satisfied: requests<3,>=2 in /opt/conda/lib/python3.11/site-packages (from langsmith<0.4,>=0.1.125->langchain-core<0.4.0,>=0.3.0->langchain-text-splitters==0.3.0) (2.32.3)\n",
      "Requirement already satisfied: requests-toolbelt<2.0.0,>=1.0.0 in /opt/conda/lib/python3.11/site-packages (from langsmith<0.4,>=0.1.125->langchain-core<0.4.0,>=0.3.0->langchain-text-splitters==0.3.0) (1.0.0)\n",
      "Requirement already satisfied: annotated-types>=0.6.0 in /opt/conda/lib/python3.11/site-packages (from pydantic<3.0.0,>=2.5.2->langchain-core<0.4.0,>=0.3.0->langchain-text-splitters==0.3.0) (0.7.0)\n",
      "Requirement already satisfied: pydantic-core==2.23.4 in /opt/conda/lib/python3.11/site-packages (from pydantic<3.0.0,>=2.5.2->langchain-core<0.4.0,>=0.3.0->langchain-text-splitters==0.3.0) (2.23.4)\n",
      "Requirement already satisfied: anyio in /opt/conda/lib/python3.11/site-packages (from httpx<1,>=0.23.0->langsmith<0.4,>=0.1.125->langchain-core<0.4.0,>=0.3.0->langchain-text-splitters==0.3.0) (4.6.0)\n",
      "Requirement already satisfied: certifi in /opt/conda/lib/python3.11/site-packages (from httpx<1,>=0.23.0->langsmith<0.4,>=0.1.125->langchain-core<0.4.0,>=0.3.0->langchain-text-splitters==0.3.0) (2024.8.30)\n",
      "Requirement already satisfied: httpcore==1.* in /opt/conda/lib/python3.11/site-packages (from httpx<1,>=0.23.0->langsmith<0.4,>=0.1.125->langchain-core<0.4.0,>=0.3.0->langchain-text-splitters==0.3.0) (1.0.6)\n",
      "Requirement already satisfied: idna in /opt/conda/lib/python3.11/site-packages (from httpx<1,>=0.23.0->langsmith<0.4,>=0.1.125->langchain-core<0.4.0,>=0.3.0->langchain-text-splitters==0.3.0) (3.7)\n",
      "Requirement already satisfied: sniffio in /opt/conda/lib/python3.11/site-packages (from httpx<1,>=0.23.0->langsmith<0.4,>=0.1.125->langchain-core<0.4.0,>=0.3.0->langchain-text-splitters==0.3.0) (1.3.1)\n",
      "Requirement already satisfied: h11<0.15,>=0.13 in /opt/conda/lib/python3.11/site-packages (from httpcore==1.*->httpx<1,>=0.23.0->langsmith<0.4,>=0.1.125->langchain-core<0.4.0,>=0.3.0->langchain-text-splitters==0.3.0) (0.14.0)\n",
      "Requirement already satisfied: charset-normalizer<4,>=2 in /opt/conda/lib/python3.11/site-packages (from requests<3,>=2->langsmith<0.4,>=0.1.125->langchain-core<0.4.0,>=0.3.0->langchain-text-splitters==0.3.0) (3.3.2)\n",
      "Requirement already satisfied: urllib3<3,>=1.21.1 in /opt/conda/lib/python3.11/site-packages (from requests<3,>=2->langsmith<0.4,>=0.1.125->langchain-core<0.4.0,>=0.3.0->langchain-text-splitters==0.3.0) (2.2.2)\n",
      "Installing collected packages: langchain-text-splitters\n",
      "  Attempting uninstall: langchain-text-splitters\n",
      "    Found existing installation: langchain-text-splitters 0.3.7\n",
      "    Uninstalling langchain-text-splitters-0.3.7:\n",
      "      Successfully uninstalled langchain-text-splitters-0.3.7\n",
      "Successfully installed langchain-text-splitters-0.3.0\n",
      "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager, possibly rendering your system unusable.It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv. Use the --root-user-action option if you know what you are doing and want to suppress this warning.\u001b[0m\u001b[33m\n",
      "\u001b[0mLooking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple\n",
      "Collecting langchain-core==0.3.0\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/75/a4/3eba5bb842219342ecd855d52febc3f3dcec3130e40bca9ab55b7ce0bd3d/langchain_core-0.3.0-py3-none-any.whl (405 kB)\n",
      "Requirement already satisfied: PyYAML>=5.3 in /opt/conda/lib/python3.11/site-packages (from langchain-core==0.3.0) (6.0.2)\n",
      "Requirement already satisfied: jsonpatch<2.0,>=1.33 in /opt/conda/lib/python3.11/site-packages (from langchain-core==0.3.0) (1.33)\n",
      "Requirement already satisfied: langsmith<0.2.0,>=0.1.117 in /opt/conda/lib/python3.11/site-packages (from langchain-core==0.3.0) (0.1.147)\n",
      "Requirement already satisfied: packaging<25,>=23.2 in /opt/conda/lib/python3.11/site-packages (from langchain-core==0.3.0) (24.1)\n",
      "Requirement already satisfied: pydantic<3.0.0,>=2.5.2 in /opt/conda/lib/python3.11/site-packages (from langchain-core==0.3.0) (2.9.2)\n",
      "Requirement already satisfied: tenacity!=8.4.0,<9.0.0,>=8.1.0 in /opt/conda/lib/python3.11/site-packages (from langchain-core==0.3.0) (8.5.0)\n",
      "Requirement already satisfied: typing-extensions>=4.7 in /opt/conda/lib/python3.11/site-packages (from langchain-core==0.3.0) (4.12.2)\n",
      "Requirement already satisfied: jsonpointer>=1.9 in /opt/conda/lib/python3.11/site-packages (from jsonpatch<2.0,>=1.33->langchain-core==0.3.0) (2.1)\n",
      "Requirement already satisfied: httpx<1,>=0.23.0 in /opt/conda/lib/python3.11/site-packages (from langsmith<0.2.0,>=0.1.117->langchain-core==0.3.0) (0.27.2)\n",
      "Requirement already satisfied: orjson<4.0.0,>=3.9.14 in /opt/conda/lib/python3.11/site-packages (from langsmith<0.2.0,>=0.1.117->langchain-core==0.3.0) (3.10.16)\n",
      "Requirement already satisfied: requests<3,>=2 in /opt/conda/lib/python3.11/site-packages (from langsmith<0.2.0,>=0.1.117->langchain-core==0.3.0) (2.32.3)\n",
      "Requirement already satisfied: requests-toolbelt<2.0.0,>=1.0.0 in /opt/conda/lib/python3.11/site-packages (from langsmith<0.2.0,>=0.1.117->langchain-core==0.3.0) (1.0.0)\n",
      "Requirement already satisfied: annotated-types>=0.6.0 in /opt/conda/lib/python3.11/site-packages (from pydantic<3.0.0,>=2.5.2->langchain-core==0.3.0) (0.7.0)\n",
      "Requirement already satisfied: pydantic-core==2.23.4 in /opt/conda/lib/python3.11/site-packages (from pydantic<3.0.0,>=2.5.2->langchain-core==0.3.0) (2.23.4)\n",
      "Requirement already satisfied: anyio in /opt/conda/lib/python3.11/site-packages (from httpx<1,>=0.23.0->langsmith<0.2.0,>=0.1.117->langchain-core==0.3.0) (4.6.0)\n",
      "Requirement already satisfied: certifi in /opt/conda/lib/python3.11/site-packages (from httpx<1,>=0.23.0->langsmith<0.2.0,>=0.1.117->langchain-core==0.3.0) (2024.8.30)\n",
      "Requirement already satisfied: httpcore==1.* in /opt/conda/lib/python3.11/site-packages (from httpx<1,>=0.23.0->langsmith<0.2.0,>=0.1.117->langchain-core==0.3.0) (1.0.6)\n",
      "Requirement already satisfied: idna in /opt/conda/lib/python3.11/site-packages (from httpx<1,>=0.23.0->langsmith<0.2.0,>=0.1.117->langchain-core==0.3.0) (3.7)\n",
      "Requirement already satisfied: sniffio in /opt/conda/lib/python3.11/site-packages (from httpx<1,>=0.23.0->langsmith<0.2.0,>=0.1.117->langchain-core==0.3.0) (1.3.1)\n",
      "Requirement already satisfied: h11<0.15,>=0.13 in /opt/conda/lib/python3.11/site-packages (from httpcore==1.*->httpx<1,>=0.23.0->langsmith<0.2.0,>=0.1.117->langchain-core==0.3.0) (0.14.0)\n",
      "Requirement already satisfied: charset-normalizer<4,>=2 in /opt/conda/lib/python3.11/site-packages (from requests<3,>=2->langsmith<0.2.0,>=0.1.117->langchain-core==0.3.0) (3.3.2)\n",
      "Requirement already satisfied: urllib3<3,>=1.21.1 in /opt/conda/lib/python3.11/site-packages (from requests<3,>=2->langsmith<0.2.0,>=0.1.117->langchain-core==0.3.0) (2.2.2)\n",
      "Installing collected packages: langchain-core\n",
      "  Attempting uninstall: langchain-core\n",
      "    Found existing installation: langchain-core 0.3.48\n",
      "    Uninstalling langchain-core-0.3.48:\n",
      "      Successfully uninstalled langchain-core-0.3.48\n",
      "Successfully installed langchain-core-0.3.0\n",
      "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager, possibly rendering your system unusable.It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv. Use the --root-user-action option if you know what you are doing and want to suppress this warning.\u001b[0m\u001b[33m\n",
      "\u001b[0mLooking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple\n",
      "Collecting langchain-openai==0.2.0\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/8c/de/865dedcb252db4725e6e458fb28845038217fdade1df40a9e41b0579c534/langchain_openai-0.2.0-py3-none-any.whl (51 kB)\n",
      "Requirement already satisfied: langchain-core<0.4,>=0.3 in /opt/conda/lib/python3.11/site-packages (from langchain-openai==0.2.0) (0.3.0)\n",
      "Requirement already satisfied: openai<2.0.0,>=1.40.0 in /opt/conda/lib/python3.11/site-packages (from langchain-openai==0.2.0) (1.51.2)\n",
      "Requirement already satisfied: tiktoken<1,>=0.7 in /opt/conda/lib/python3.11/site-packages (from langchain-openai==0.2.0) (0.8.0)\n",
      "Requirement already satisfied: PyYAML>=5.3 in /opt/conda/lib/python3.11/site-packages (from langchain-core<0.4,>=0.3->langchain-openai==0.2.0) (6.0.2)\n",
      "Requirement already satisfied: jsonpatch<2.0,>=1.33 in /opt/conda/lib/python3.11/site-packages (from langchain-core<0.4,>=0.3->langchain-openai==0.2.0) (1.33)\n",
      "Requirement already satisfied: langsmith<0.2.0,>=0.1.117 in /opt/conda/lib/python3.11/site-packages (from langchain-core<0.4,>=0.3->langchain-openai==0.2.0) (0.1.147)\n",
      "Requirement already satisfied: packaging<25,>=23.2 in /opt/conda/lib/python3.11/site-packages (from langchain-core<0.4,>=0.3->langchain-openai==0.2.0) (24.1)\n",
      "Requirement already satisfied: pydantic<3.0.0,>=2.5.2 in /opt/conda/lib/python3.11/site-packages (from langchain-core<0.4,>=0.3->langchain-openai==0.2.0) (2.9.2)\n",
      "Requirement already satisfied: tenacity!=8.4.0,<9.0.0,>=8.1.0 in /opt/conda/lib/python3.11/site-packages (from langchain-core<0.4,>=0.3->langchain-openai==0.2.0) (8.5.0)\n",
      "Requirement already satisfied: typing-extensions>=4.7 in /opt/conda/lib/python3.11/site-packages (from langchain-core<0.4,>=0.3->langchain-openai==0.2.0) (4.12.2)\n",
      "Requirement already satisfied: anyio<5,>=3.5.0 in /opt/conda/lib/python3.11/site-packages (from openai<2.0.0,>=1.40.0->langchain-openai==0.2.0) (4.6.0)\n",
      "Requirement already satisfied: distro<2,>=1.7.0 in /opt/conda/lib/python3.11/site-packages (from openai<2.0.0,>=1.40.0->langchain-openai==0.2.0) (1.9.0)\n",
      "Requirement already satisfied: httpx<1,>=0.23.0 in /opt/conda/lib/python3.11/site-packages (from openai<2.0.0,>=1.40.0->langchain-openai==0.2.0) (0.27.2)\n",
      "Requirement already satisfied: jiter<1,>=0.4.0 in /opt/conda/lib/python3.11/site-packages (from openai<2.0.0,>=1.40.0->langchain-openai==0.2.0) (0.6.1)\n",
      "Requirement already satisfied: sniffio in /opt/conda/lib/python3.11/site-packages (from openai<2.0.0,>=1.40.0->langchain-openai==0.2.0) (1.3.1)\n",
      "Requirement already satisfied: tqdm>4 in /opt/conda/lib/python3.11/site-packages (from openai<2.0.0,>=1.40.0->langchain-openai==0.2.0) (4.66.4)\n",
      "Requirement already satisfied: regex>=2022.1.18 in /opt/conda/lib/python3.11/site-packages (from tiktoken<1,>=0.7->langchain-openai==0.2.0) (2024.9.11)\n",
      "Requirement already satisfied: requests>=2.26.0 in /opt/conda/lib/python3.11/site-packages (from tiktoken<1,>=0.7->langchain-openai==0.2.0) (2.32.3)\n",
      "Requirement already satisfied: idna>=2.8 in /opt/conda/lib/python3.11/site-packages (from anyio<5,>=3.5.0->openai<2.0.0,>=1.40.0->langchain-openai==0.2.0) (3.7)\n",
      "Requirement already satisfied: certifi in /opt/conda/lib/python3.11/site-packages (from httpx<1,>=0.23.0->openai<2.0.0,>=1.40.0->langchain-openai==0.2.0) (2024.8.30)\n",
      "Requirement already satisfied: httpcore==1.* in /opt/conda/lib/python3.11/site-packages (from httpx<1,>=0.23.0->openai<2.0.0,>=1.40.0->langchain-openai==0.2.0) (1.0.6)\n",
      "Requirement already satisfied: h11<0.15,>=0.13 in /opt/conda/lib/python3.11/site-packages (from httpcore==1.*->httpx<1,>=0.23.0->openai<2.0.0,>=1.40.0->langchain-openai==0.2.0) (0.14.0)\n",
      "Requirement already satisfied: jsonpointer>=1.9 in /opt/conda/lib/python3.11/site-packages (from jsonpatch<2.0,>=1.33->langchain-core<0.4,>=0.3->langchain-openai==0.2.0) (2.1)\n",
      "Requirement already satisfied: orjson<4.0.0,>=3.9.14 in /opt/conda/lib/python3.11/site-packages (from langsmith<0.2.0,>=0.1.117->langchain-core<0.4,>=0.3->langchain-openai==0.2.0) (3.10.16)\n",
      "Requirement already satisfied: requests-toolbelt<2.0.0,>=1.0.0 in /opt/conda/lib/python3.11/site-packages (from langsmith<0.2.0,>=0.1.117->langchain-core<0.4,>=0.3->langchain-openai==0.2.0) (1.0.0)\n",
      "Requirement already satisfied: annotated-types>=0.6.0 in /opt/conda/lib/python3.11/site-packages (from pydantic<3.0.0,>=2.5.2->langchain-core<0.4,>=0.3->langchain-openai==0.2.0) (0.7.0)\n",
      "Requirement already satisfied: pydantic-core==2.23.4 in /opt/conda/lib/python3.11/site-packages (from pydantic<3.0.0,>=2.5.2->langchain-core<0.4,>=0.3->langchain-openai==0.2.0) (2.23.4)\n",
      "Requirement already satisfied: charset-normalizer<4,>=2 in /opt/conda/lib/python3.11/site-packages (from requests>=2.26.0->tiktoken<1,>=0.7->langchain-openai==0.2.0) (3.3.2)\n",
      "Requirement already satisfied: urllib3<3,>=1.21.1 in /opt/conda/lib/python3.11/site-packages (from requests>=2.26.0->tiktoken<1,>=0.7->langchain-openai==0.2.0) (2.2.2)\n",
      "Installing collected packages: langchain-openai\n",
      "Successfully installed langchain-openai-0.2.0\n",
      "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager, possibly rendering your system unusable.It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv. Use the --root-user-action option if you know what you are doing and want to suppress this warning.\u001b[0m\u001b[33m\n",
      "\u001b[0mLooking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple\n",
      "Collecting langchain-chroma==0.1.4\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/bc/8c/ef0a589e523e72373a79a64cd1184682155113b865f889d815a9f264a755/langchain_chroma-0.1.4-py3-none-any.whl (10 kB)\n",
      "Collecting chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0 (from langchain-chroma==0.1.4)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/92/8c/a9eb95a28e6c35a0122417976a9d435eeaceb53f596a8973e33b3dd4cfac/chromadb-0.5.23-py3-none-any.whl (628 kB)\n",
      "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m628.3/628.3 kB\u001b[0m \u001b[31m7.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[?25hRequirement already satisfied: fastapi<1,>=0.95.2 in /opt/conda/lib/python3.11/site-packages (from langchain-chroma==0.1.4) (0.115.0)\n",
      "Requirement already satisfied: langchain-core<0.4,>=0.1.40 in /opt/conda/lib/python3.11/site-packages (from langchain-chroma==0.1.4) (0.3.0)\n",
      "Requirement already satisfied: numpy<2,>=1 in /opt/conda/lib/python3.11/site-packages (from langchain-chroma==0.1.4) (1.24.3)\n",
      "Collecting build>=1.0.3 (from chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/84/c2/80633736cd183ee4a62107413def345f7e6e3c01563dbca1417363cf957e/build-1.2.2.post1-py3-none-any.whl (22 kB)\n",
      "Requirement already satisfied: pydantic>=1.9 in /opt/conda/lib/python3.11/site-packages (from chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4) (2.9.2)\n",
      "Collecting chroma-hnswlib==0.7.6 (from chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/c7/2d/d5663e134436e5933bc63516a20b5edc08b4c1b1588b9680908a5f1afd04/chroma_hnswlib-0.7.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.4 MB)\n",
      "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m2.4/2.4 MB\u001b[0m \u001b[31m8.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0ma \u001b[36m0:00:01\u001b[0m\n",
      "\u001b[?25hRequirement already satisfied: uvicorn>=0.18.3 in /opt/conda/lib/python3.11/site-packages (from uvicorn[standard]>=0.18.3->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4) (0.31.1)\n",
      "Collecting posthog>=2.4.0 (from chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/82/c7/4d9bf5d8ec29f9bab4c5c5ff2570748e7db53f98264ce2710406fcc2bbbd/posthog-3.21.0-py2.py3-none-any.whl (79 kB)\n",
      "Requirement already satisfied: typing_extensions>=4.5.0 in /opt/conda/lib/python3.11/site-packages (from chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4) (4.12.2)\n",
      "Collecting onnxruntime>=1.14.1 (from chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/f9/49/1e916e8d1d957a1432c1662ef2e94f3e4afab31f6f1888fb80d4da374a5d/onnxruntime-1.21.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (16.0 MB)\n",
      "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m16.0/16.0 MB\u001b[0m \u001b[31m16.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0ma \u001b[36m0:00:01\u001b[0m\n",
      "\u001b[?25hCollecting opentelemetry-api>=1.2.0 (from chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/6c/c8/86557ff0da32f3817bc4face57ea35cfdc2f9d3bcefd42311ef860dcefb7/opentelemetry_api-1.31.1-py3-none-any.whl (65 kB)\n",
      "Collecting opentelemetry-exporter-otlp-proto-grpc>=1.2.0 (from chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/ee/25/9974fa3a431d7499bd9d179fb9bd7daaa3ad9eba3313f72da5226b6d02df/opentelemetry_exporter_otlp_proto_grpc-1.31.1-py3-none-any.whl (18 kB)\n",
      "Collecting opentelemetry-instrumentation-fastapi>=0.41b0 (from chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/23/89/acef7f625b218523873e32584dc5243d95ffa4facba737fd8b854c049c58/opentelemetry_instrumentation_fastapi-0.52b1-py3-none-any.whl (12 kB)\n",
      "Collecting opentelemetry-sdk>=1.2.0 (from chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/bc/36/758e5d3746bc86a2af20aa5e2236a7c5aa4264b501dc0e9f40efd9078ef0/opentelemetry_sdk-1.31.1-py3-none-any.whl (118 kB)\n",
      "Requirement already satisfied: tokenizers<=0.20.3,>=0.13.2 in /opt/conda/lib/python3.11/site-packages (from chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4) (0.15.0)\n",
      "Collecting pypika>=0.48.9 (from chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/c7/2c/94ed7b91db81d61d7096ac8f2d325ec562fc75e35f3baea8749c85b28784/PyPika-0.48.9.tar.gz (67 kB)\n",
      "  Installing build dependencies ... \u001b[?25ldone\n",
      "\u001b[?25h  Getting requirements to build wheel ... \u001b[?25ldone\n",
      "\u001b[?25h  Preparing metadata (pyproject.toml) ... \u001b[?25ldone\n",
      "\u001b[?25hRequirement already satisfied: tqdm>=4.65.0 in /opt/conda/lib/python3.11/site-packages (from chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4) (4.66.4)\n",
      "Requirement already satisfied: overrides>=7.3.1 in /opt/conda/lib/python3.11/site-packages (from chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4) (7.7.0)\n",
      "Collecting importlib-resources (from chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/a4/ed/1f1afb2e9e7f38a545d628f864d562a5ae64fe6f7a10e28ffb9b185b4e89/importlib_resources-6.5.2-py3-none-any.whl (37 kB)\n",
      "Collecting grpcio>=1.58.0 (from chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/c7/67/cbd63c485051eb78663355d9efd1b896cfb50d4a220581ec2cb9a15cd750/grpcio-1.71.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (5.9 MB)\n",
      "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m5.9/5.9 MB\u001b[0m \u001b[31m13.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0ma \u001b[36m0:00:01\u001b[0m\n",
      "\u001b[?25hCollecting bcrypt>=4.0.1 (from chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/dc/7f/1e36379e169a7df3a14a1c160a49b7b918600a6008de43ff20d479e6f4b5/bcrypt-4.3.0-cp39-abi3-manylinux_2_34_x86_64.whl (284 kB)\n",
      "Collecting typer>=0.9.0 (from chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/7f/fc/5b29fea8cee020515ca82cc68e3b8e1e34bb19a3535ad854cac9257b414c/typer-0.15.2-py3-none-any.whl (45 kB)\n",
      "Collecting kubernetes>=28.1.0 (from chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/08/10/9f8af3e6f569685ce3af7faab51c8dd9d93b9c38eba339ca31c746119447/kubernetes-32.0.1-py2.py3-none-any.whl (2.0 MB)\n",
      "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m2.0/2.0 MB\u001b[0m \u001b[31m29.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[?25hRequirement already satisfied: tenacity>=8.2.3 in /opt/conda/lib/python3.11/site-packages (from chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4) (8.5.0)\n",
      "Requirement already satisfied: PyYAML>=6.0.0 in /opt/conda/lib/python3.11/site-packages (from chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4) (6.0.2)\n",
      "Collecting mmh3>=4.0.1 (from chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/ac/aa/8bc964067df9262740c95e4cde2d19f149f2224f426654e14199a9e47df6/mmh3-5.1.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl (101 kB)\n",
      "Requirement already satisfied: orjson>=3.9.12 in /opt/conda/lib/python3.11/site-packages (from chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4) (3.10.16)\n",
      "Requirement already satisfied: httpx>=0.27.0 in /opt/conda/lib/python3.11/site-packages (from chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4) (0.27.2)\n",
      "Requirement already satisfied: rich>=10.11.0 in /opt/conda/lib/python3.11/site-packages (from chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4) (13.9.2)\n",
      "Requirement already satisfied: starlette<0.39.0,>=0.37.2 in /opt/conda/lib/python3.11/site-packages (from fastapi<1,>=0.95.2->langchain-chroma==0.1.4) (0.38.6)\n",
      "Requirement already satisfied: jsonpatch<2.0,>=1.33 in /opt/conda/lib/python3.11/site-packages (from langchain-core<0.4,>=0.1.40->langchain-chroma==0.1.4) (1.33)\n",
      "Requirement already satisfied: langsmith<0.2.0,>=0.1.117 in /opt/conda/lib/python3.11/site-packages (from langchain-core<0.4,>=0.1.40->langchain-chroma==0.1.4) (0.1.147)\n",
      "Requirement already satisfied: packaging<25,>=23.2 in /opt/conda/lib/python3.11/site-packages (from langchain-core<0.4,>=0.1.40->langchain-chroma==0.1.4) (24.1)\n",
      "Collecting pyproject_hooks (from build>=1.0.3->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/bd/24/12818598c362d7f300f18e74db45963dbcb85150324092410c8b49405e42/pyproject_hooks-1.2.0-py3-none-any.whl (10 kB)\n",
      "Requirement already satisfied: anyio in /opt/conda/lib/python3.11/site-packages (from httpx>=0.27.0->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4) (4.6.0)\n",
      "Requirement already satisfied: certifi in /opt/conda/lib/python3.11/site-packages (from httpx>=0.27.0->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4) (2024.8.30)\n",
      "Requirement already satisfied: httpcore==1.* in /opt/conda/lib/python3.11/site-packages (from httpx>=0.27.0->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4) (1.0.6)\n",
      "Requirement already satisfied: idna in /opt/conda/lib/python3.11/site-packages (from httpx>=0.27.0->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4) (3.7)\n",
      "Requirement already satisfied: sniffio in /opt/conda/lib/python3.11/site-packages (from httpx>=0.27.0->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4) (1.3.1)\n",
      "Requirement already satisfied: h11<0.15,>=0.13 in /opt/conda/lib/python3.11/site-packages (from httpcore==1.*->httpx>=0.27.0->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4) (0.14.0)\n",
      "Requirement already satisfied: jsonpointer>=1.9 in /opt/conda/lib/python3.11/site-packages (from jsonpatch<2.0,>=1.33->langchain-core<0.4,>=0.1.40->langchain-chroma==0.1.4) (2.1)\n",
      "Requirement already satisfied: six>=1.9.0 in /opt/conda/lib/python3.11/site-packages (from kubernetes>=28.1.0->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4) (1.16.0)\n",
      "Requirement already satisfied: python-dateutil>=2.5.3 in /opt/conda/lib/python3.11/site-packages (from kubernetes>=28.1.0->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4) (2.9.0.post0)\n",
      "Collecting google-auth>=1.0.1 (from kubernetes>=28.1.0->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/9d/47/603554949a37bca5b7f894d51896a9c534b9eab808e2520a748e081669d0/google_auth-2.38.0-py2.py3-none-any.whl (210 kB)\n",
      "Requirement already satisfied: websocket-client!=0.40.0,!=0.41.*,!=0.42.*,>=0.32.0 in /opt/conda/lib/python3.11/site-packages (from kubernetes>=28.1.0->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4) (1.8.0)\n",
      "Requirement already satisfied: requests in /opt/conda/lib/python3.11/site-packages (from kubernetes>=28.1.0->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4) (2.32.3)\n",
      "Collecting requests-oauthlib (from kubernetes>=28.1.0->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/3b/5d/63d4ae3b9daea098d5d6f5da83984853c1bbacd5dc826764b249fe119d24/requests_oauthlib-2.0.0-py2.py3-none-any.whl (24 kB)\n",
      "Collecting oauthlib>=3.2.2 (from kubernetes>=28.1.0->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/7e/80/cab10959dc1faead58dc8384a781dfbf93cb4d33d50988f7a69f1b7c9bbe/oauthlib-3.2.2-py3-none-any.whl (151 kB)\n",
      "Requirement already satisfied: urllib3>=1.24.2 in /opt/conda/lib/python3.11/site-packages (from kubernetes>=28.1.0->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4) (2.2.2)\n",
      "Collecting durationpy>=0.7 (from kubernetes>=28.1.0->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/4c/a3/ac312faeceffd2d8f86bc6dcb5c401188ba5a01bc88e69bed97578a0dfcd/durationpy-0.9-py3-none-any.whl (3.5 kB)\n",
      "Requirement already satisfied: requests-toolbelt<2.0.0,>=1.0.0 in /opt/conda/lib/python3.11/site-packages (from langsmith<0.2.0,>=0.1.117->langchain-core<0.4,>=0.1.40->langchain-chroma==0.1.4) (1.0.0)\n",
      "Collecting coloredlogs (from onnxruntime>=1.14.1->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/a7/06/3d6badcf13db419e25b07041d9c7b4a2c331d3f4e7134445ec5df57714cd/coloredlogs-15.0.1-py2.py3-none-any.whl (46 kB)\n",
      "Collecting flatbuffers (from onnxruntime>=1.14.1->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/b8/25/155f9f080d5e4bc0082edfda032ea2bc2b8fab3f4d25d46c1e9dd22a1a89/flatbuffers-25.2.10-py2.py3-none-any.whl (30 kB)\n",
      "Requirement already satisfied: protobuf in /opt/conda/lib/python3.11/site-packages (from onnxruntime>=1.14.1->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4) (5.28.2)\n",
      "Requirement already satisfied: sympy in /opt/conda/lib/python3.11/site-packages (from onnxruntime>=1.14.1->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4) (1.13.3)\n",
      "Collecting deprecated>=1.2.6 (from opentelemetry-api>=1.2.0->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/6e/c6/ac0b6c1e2d138f1002bcf799d330bd6d85084fece321e662a14223794041/Deprecated-1.2.18-py2.py3-none-any.whl (10.0 kB)\n",
      "Requirement already satisfied: importlib-metadata<8.7.0,>=6.0 in /opt/conda/lib/python3.11/site-packages (from opentelemetry-api>=1.2.0->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4) (8.5.0)\n",
      "Collecting googleapis-common-protos~=1.52 (from opentelemetry-exporter-otlp-proto-grpc>=1.2.0->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/f9/53/d35476d547a286506f0a6a634ccf1e5d288fffd53d48f0bd5fef61d68684/googleapis_common_protos-1.69.2-py3-none-any.whl (293 kB)\n",
      "Collecting opentelemetry-exporter-otlp-proto-common==1.31.1 (from opentelemetry-exporter-otlp-proto-grpc>=1.2.0->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/82/70/134282413000a3fc02e6b4e301b8c5d7127c43b50bd23cddbaf406ab33ff/opentelemetry_exporter_otlp_proto_common-1.31.1-py3-none-any.whl (18 kB)\n",
      "Collecting opentelemetry-proto==1.31.1 (from opentelemetry-exporter-otlp-proto-grpc>=1.2.0->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/b6/f1/3baee86eab4f1b59b755f3c61a9b5028f380c88250bb9b7f89340502dbba/opentelemetry_proto-1.31.1-py3-none-any.whl (55 kB)\n",
      "Collecting opentelemetry-instrumentation-asgi==0.52b1 (from opentelemetry-instrumentation-fastapi>=0.41b0->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/19/de/39ec078ae94a365d2f434b7e25886c267864aca5695b48fa5b60f80fbfb3/opentelemetry_instrumentation_asgi-0.52b1-py3-none-any.whl (16 kB)\n",
      "Collecting opentelemetry-instrumentation==0.52b1 (from opentelemetry-instrumentation-fastapi>=0.41b0->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/61/dd/a2b35078170941990e7a5194b9600fa75868958a9a2196a752da0e7b97a0/opentelemetry_instrumentation-0.52b1-py3-none-any.whl (31 kB)\n",
      "Collecting opentelemetry-semantic-conventions==0.52b1 (from opentelemetry-instrumentation-fastapi>=0.41b0->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/98/be/d4ba300cfc1d4980886efbc9b48ee75242b9fcf940d9c4ccdc9ef413a7cf/opentelemetry_semantic_conventions-0.52b1-py3-none-any.whl (183 kB)\n",
      "Collecting opentelemetry-util-http==0.52b1 (from opentelemetry-instrumentation-fastapi>=0.41b0->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/2c/00/1591b397c9efc0e4215d223553a1cb9090c8499888a4447f842443077d31/opentelemetry_util_http-0.52b1-py3-none-any.whl (7.3 kB)\n",
      "Collecting wrapt<2.0.0,>=1.0.0 (from opentelemetry-instrumentation==0.52b1->opentelemetry-instrumentation-fastapi>=0.41b0->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/b4/b0/9fc566b0fe08b282c850063591a756057c3247b2362b9286429ec5bf1721/wrapt-1.17.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl (83 kB)\n",
      "Collecting asgiref~=3.0 (from opentelemetry-instrumentation-asgi==0.52b1->opentelemetry-instrumentation-fastapi>=0.41b0->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/39/e3/893e8757be2612e6c266d9bb58ad2e3651524b5b40cf56761e985a28b13e/asgiref-3.8.1-py3-none-any.whl (23 kB)\n",
      "Collecting monotonic>=1.5 (from posthog>=2.4.0->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/9a/67/7e8406a29b6c45be7af7740456f7f37025f0506ae2e05fb9009a53946860/monotonic-1.6-py2.py3-none-any.whl (8.2 kB)\n",
      "Collecting backoff>=1.10.0 (from posthog>=2.4.0->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/df/73/b6e24bd22e6720ca8ee9a85a0c4a2971af8497d8f3193fa05390cbd46e09/backoff-2.2.1-py3-none-any.whl (15 kB)\n",
      "Requirement already satisfied: distro>=1.5.0 in /opt/conda/lib/python3.11/site-packages (from posthog>=2.4.0->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4) (1.9.0)\n",
      "Requirement already satisfied: annotated-types>=0.6.0 in /opt/conda/lib/python3.11/site-packages (from pydantic>=1.9->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4) (0.7.0)\n",
      "Requirement already satisfied: pydantic-core==2.23.4 in /opt/conda/lib/python3.11/site-packages (from pydantic>=1.9->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4) (2.23.4)\n",
      "Requirement already satisfied: markdown-it-py>=2.2.0 in /opt/conda/lib/python3.11/site-packages (from rich>=10.11.0->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4) (3.0.0)\n",
      "Requirement already satisfied: pygments<3.0.0,>=2.13.0 in /opt/conda/lib/python3.11/site-packages (from rich>=10.11.0->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4) (2.18.0)\n",
      "Requirement already satisfied: huggingface_hub<1.0,>=0.16.4 in /opt/conda/lib/python3.11/site-packages (from tokenizers<=0.20.3,>=0.13.2->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4) (0.25.2)\n",
      "Requirement already satisfied: click>=8.0.0 in /opt/conda/lib/python3.11/site-packages (from typer>=0.9.0->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4) (8.1.7)\n",
      "Collecting shellingham>=1.3.0 (from typer>=0.9.0->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl (9.8 kB)\n",
      "Requirement already satisfied: httptools>=0.5.0 in /opt/conda/lib/python3.11/site-packages (from uvicorn[standard]>=0.18.3->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4) (0.6.1)\n",
      "Requirement already satisfied: python-dotenv>=0.13 in /opt/conda/lib/python3.11/site-packages (from uvicorn[standard]>=0.18.3->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4) (1.0.1)\n",
      "Requirement already satisfied: uvloop!=0.15.0,!=0.15.1,>=0.14.0 in /opt/conda/lib/python3.11/site-packages (from uvicorn[standard]>=0.18.3->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4) (0.20.0)\n",
      "Requirement already satisfied: watchfiles>=0.13 in /opt/conda/lib/python3.11/site-packages (from uvicorn[standard]>=0.18.3->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4) (0.24.0)\n",
      "Requirement already satisfied: websockets>=10.4 in /opt/conda/lib/python3.11/site-packages (from uvicorn[standard]>=0.18.3->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4) (13.1)\n",
      "Collecting cachetools<6.0,>=2.0.0 (from google-auth>=1.0.1->kubernetes>=28.1.0->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/72/76/20fa66124dbe6be5cafeb312ece67de6b61dd91a0247d1ea13db4ebb33c2/cachetools-5.5.2-py3-none-any.whl (10 kB)\n",
      "Collecting pyasn1-modules>=0.2.1 (from google-auth>=1.0.1->kubernetes>=28.1.0->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/77/89/bc88a6711935ba795a679ea6ebee07e128050d6382eaa35a0a47c8032bdc/pyasn1_modules-0.4.1-py3-none-any.whl (181 kB)\n",
      "Collecting rsa<5,>=3.1.4 (from google-auth>=1.0.1->kubernetes>=28.1.0->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/49/97/fa78e3d2f65c02c8e1268b9aba606569fe97f6c8f7c2d74394553347c145/rsa-4.9-py3-none-any.whl (34 kB)\n",
      "Requirement already satisfied: filelock in /opt/conda/lib/python3.11/site-packages (from huggingface_hub<1.0,>=0.16.4->tokenizers<=0.20.3,>=0.13.2->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4) (3.16.1)\n",
      "Requirement already satisfied: fsspec>=2023.5.0 in /opt/conda/lib/python3.11/site-packages (from huggingface_hub<1.0,>=0.16.4->tokenizers<=0.20.3,>=0.13.2->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4) (2024.6.1)\n",
      "Requirement already satisfied: zipp>=3.20 in /opt/conda/lib/python3.11/site-packages (from importlib-metadata<8.7.0,>=6.0->opentelemetry-api>=1.2.0->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4) (3.20.2)\n",
      "Requirement already satisfied: mdurl~=0.1 in /opt/conda/lib/python3.11/site-packages (from markdown-it-py>=2.2.0->rich>=10.11.0->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4) (0.1.2)\n",
      "Requirement already satisfied: charset-normalizer<4,>=2 in /opt/conda/lib/python3.11/site-packages (from requests->kubernetes>=28.1.0->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4) (3.3.2)\n",
      "Collecting humanfriendly>=9.1 (from coloredlogs->onnxruntime>=1.14.1->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/f0/0f/310fb31e39e2d734ccaa2c0fb981ee41f7bd5056ce9bc29b2248bd569169/humanfriendly-10.0-py2.py3-none-any.whl (86 kB)\n",
      "Requirement already satisfied: mpmath<1.4,>=1.1.0 in /opt/conda/lib/python3.11/site-packages (from sympy->onnxruntime>=1.14.1->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4) (1.3.0)\n",
      "Collecting pyasn1<0.7.0,>=0.4.6 (from pyasn1-modules>=0.2.1->google-auth>=1.0.1->kubernetes>=28.1.0->chromadb!=0.5.4,!=0.5.5,<0.6.0,>=0.4.0->langchain-chroma==0.1.4)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/c8/f1/d6a797abb14f6283c0ddff96bbdd46937f64122b8c925cab503dd37f8214/pyasn1-0.6.1-py3-none-any.whl (83 kB)\n",
      "Building wheels for collected packages: pypika\n",
      "  Building wheel for pypika (pyproject.toml) ... \u001b[?25ldone\n",
      "\u001b[?25h  Created wheel for pypika: filename=pypika-0.48.9-py2.py3-none-any.whl size=53800 sha256=b482d28fc70eefe5decd5201a41b5b20645d470d19196d1e635102dc51d95927\n",
      "  Stored in directory: /root/.cache/pip/wheels/4d/c1/21/7df1c75fdaed1a94b0ce4abafce48c11d330b7236b93560b1c\n",
      "Successfully built pypika\n",
      "Installing collected packages: pypika, monotonic, flatbuffers, durationpy, wrapt, shellingham, pyproject_hooks, pyasn1, opentelemetry-util-http, opentelemetry-proto, oauthlib, mmh3, importlib-resources, humanfriendly, grpcio, googleapis-common-protos, chroma-hnswlib, cachetools, bcrypt, backoff, asgiref, rsa, requests-oauthlib, pyasn1-modules, posthog, opentelemetry-exporter-otlp-proto-common, deprecated, coloredlogs, build, typer, opentelemetry-api, onnxruntime, google-auth, opentelemetry-semantic-conventions, kubernetes, opentelemetry-sdk, opentelemetry-instrumentation, opentelemetry-instrumentation-asgi, opentelemetry-exporter-otlp-proto-grpc, opentelemetry-instrumentation-fastapi, chromadb, langchain-chroma\n",
      "Successfully installed asgiref-3.8.1 backoff-2.2.1 bcrypt-4.3.0 build-1.2.2.post1 cachetools-5.5.2 chroma-hnswlib-0.7.6 chromadb-0.5.23 coloredlogs-15.0.1 deprecated-1.2.18 durationpy-0.9 flatbuffers-25.2.10 google-auth-2.38.0 googleapis-common-protos-1.69.2 grpcio-1.71.0 humanfriendly-10.0 importlib-resources-6.5.2 kubernetes-32.0.1 langchain-chroma-0.1.4 mmh3-5.1.0 monotonic-1.6 oauthlib-3.2.2 onnxruntime-1.21.0 opentelemetry-api-1.31.1 opentelemetry-exporter-otlp-proto-common-1.31.1 opentelemetry-exporter-otlp-proto-grpc-1.31.1 opentelemetry-instrumentation-0.52b1 opentelemetry-instrumentation-asgi-0.52b1 opentelemetry-instrumentation-fastapi-0.52b1 opentelemetry-proto-1.31.1 opentelemetry-sdk-1.31.1 opentelemetry-semantic-conventions-0.52b1 opentelemetry-util-http-0.52b1 posthog-3.21.0 pyasn1-0.6.1 pyasn1-modules-0.4.1 pypika-0.48.9 pyproject_hooks-1.2.0 requests-oauthlib-2.0.0 rsa-4.9 shellingham-1.5.4 typer-0.15.2 wrapt-1.17.2\n",
      "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager, possibly rendering your system unusable.It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv. Use the --root-user-action option if you know what you are doing and want to suppress this warning.\u001b[0m\u001b[33m\n",
      "\u001b[0m"
     ]
    }
   ],
   "source": [
    "# 安装 langchain\n",
    "! pip install langchain==0.3.0\n",
    "! pip install langchain-community==0.3.0\n",
    "! pip install langchain-text-splitters==0.3.0\n",
    "! pip install langchain-core==0.3.0\n",
    "! pip install langchain-openai==0.2.0\n",
    "! pip install langchain-chroma==0.1.4"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "95ed11d3-9ae2-4eed-ad77-1c08ac6ee2c2",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 封装成 Langchain 可调用的类\n",
    "'''需要根据使用的 LLM API 进行修改'''\n",
    "\n",
    "from langchain.llms.base import LLM\n",
    "from typing import Any, List, Optional\n",
    "from langchain.callbacks.manager import CallbackManagerForLLMRun\n",
    "\n",
    "class DeepSeekLLM(LLM):\n",
    "    # 基于DeepSeek 接口自定义 LLM 类\n",
    "    api_key : str = None\n",
    "    model: str = None\n",
    "\n",
    "    def __init__(self, api_key=None, model=None):\n",
    "        # model：选择使用的模型\n",
    "        # 从本地初始化模型\n",
    "        super().__init__()\n",
    "        self.api_key = api_key\n",
    "        self.model = model\n",
    "\n",
    "\n",
    "    def _call(self, prompt : str, stop: Optional[List[str]] = None,\n",
    "                run_manager: Optional[CallbackManagerForLLMRun] = None,\n",
    "                **kwargs: Any):\n",
    "        # 重写调用函数\n",
    "        '''在该方法中实现调用 LLM API 的逻辑'''\n",
    "        response = get_response(prompt)    \n",
    "        return response\n",
    "        \n",
    "    @property\n",
    "    def _llm_type(self) -> str:\n",
    "        return \"DeepSeek R1\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9048f3d5-1d05-49d0-9e40-a6d900d183e0",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'<think>\\n好的，用户问我“你是谁”，我需要详细思考一下如何回答。首先，我应该明确自己的身份，用户提到我是一个有用的助手，所以我的定义应该基于这个。我需要解释自己是一个AI助手，由深度求索公司开发，而不是真实存在的人。\\n\\n接下来，我应该说明我的主要功能，比如提供信息帮助、解答问题、提供建议等。同时，要强调我擅长的领域，如自然语言处理，能够处理多种任务，比如翻译、写作、编程等，这样用户能更好地了解我的能力范围。\\n\\n然后，我需要提到我的局限性，比如无法实时更新知识库，无法执行真实世界的操作，或者理解某些复杂的情感和上下文。这有助于用户明确我的能力边界，避免产生误解。\\n\\n此外，我应该鼓励用户随时提问，并简要说明如何更好地帮助他们，比如提供具体的问题或背景信息。这样可以引导用户更有效地利用我的服务。\\n\\n最后，保持回答的正式但又不失亲切，确保信息清晰易懂，同时避免使用过于技术化的术语，让用户容易理解。整个思考过程需要逻辑清晰，结构合理，确保回答全面而准确。\\n</think>\\n\\n您好！我是由深度求索（DeepSeek）公司开发的智能助手DeepSeek-R1。如您有任何任何问题，我会尽我所能为您提供帮助。'"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "'''DEEPSEEK_API_KEY 是所调用 API 的 API Key'''\n",
    "llm = DeepSeekLLM(api_key = DEEPSEEK_API_KEY)\n",
    "llm.invoke(\"你是谁\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "09254cd7-7db9-4ae3-937c-d908bbdc082e",
   "metadata": {},
   "source": [
    "2. 调用 Embedding 模型"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6c73d46e-68bc-4448-a286-1b6c0be08b6d",
   "metadata": {},
   "source": [
    "Embedding 模型可以通过以下两种方式：\n",
    "- 使用 LLM 平台提供的 API，同上，可以自行在平台查找示例代码；\n",
    "- 从 Huggingface 下载开源 Embedding 模型，然后进行本地部署，此处用本地部署开源 Embedding 模型作为示例\n",
    "\n",
    "下载 embedding 模型：在终端 python download_model.py"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "2cc6f96e-f91d-43a1-bf58-f7b0b261ee02",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple\n",
      "Collecting accelerate\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/70/83/167d4b638bb758a966828eb8d23c5e7047825edfdf768ff5f4fb01440063/accelerate-1.5.2-py3-none-any.whl (345 kB)\n",
      "Requirement already satisfied: numpy<3.0.0,>=1.17 in /opt/conda/lib/python3.11/site-packages (from accelerate) (1.24.3)\n",
      "Requirement already satisfied: packaging>=20.0 in /opt/conda/lib/python3.11/site-packages (from accelerate) (24.1)\n",
      "Requirement already satisfied: psutil in /opt/conda/lib/python3.11/site-packages (from accelerate) (6.0.0)\n",
      "Requirement already satisfied: pyyaml in /opt/conda/lib/python3.11/site-packages (from accelerate) (6.0.2)\n",
      "Requirement already satisfied: torch>=2.0.0 in /opt/conda/lib/python3.11/site-packages (from accelerate) (2.3.0+das.opt1.dtk24042)\n",
      "Requirement already satisfied: huggingface-hub>=0.21.0 in /opt/conda/lib/python3.11/site-packages (from accelerate) (0.25.2)\n",
      "Requirement already satisfied: safetensors>=0.4.3 in /opt/conda/lib/python3.11/site-packages (from accelerate) (0.4.5)\n",
      "Requirement already satisfied: filelock in /opt/conda/lib/python3.11/site-packages (from huggingface-hub>=0.21.0->accelerate) (3.16.1)\n",
      "Requirement already satisfied: fsspec>=2023.5.0 in /opt/conda/lib/python3.11/site-packages (from huggingface-hub>=0.21.0->accelerate) (2024.6.1)\n",
      "Requirement already satisfied: requests in /opt/conda/lib/python3.11/site-packages (from huggingface-hub>=0.21.0->accelerate) (2.32.3)\n",
      "Requirement already satisfied: tqdm>=4.42.1 in /opt/conda/lib/python3.11/site-packages (from huggingface-hub>=0.21.0->accelerate) (4.66.4)\n",
      "Requirement already satisfied: typing-extensions>=3.7.4.3 in /opt/conda/lib/python3.11/site-packages (from huggingface-hub>=0.21.0->accelerate) (4.12.2)\n",
      "Requirement already satisfied: sympy in /opt/conda/lib/python3.11/site-packages (from torch>=2.0.0->accelerate) (1.13.3)\n",
      "Requirement already satisfied: networkx in /opt/conda/lib/python3.11/site-packages (from torch>=2.0.0->accelerate) (3.3)\n",
      "Requirement already satisfied: jinja2 in /opt/conda/lib/python3.11/site-packages (from torch>=2.0.0->accelerate) (3.1.4)\n",
      "Requirement already satisfied: MarkupSafe>=2.0 in /opt/conda/lib/python3.11/site-packages (from jinja2->torch>=2.0.0->accelerate) (3.0.1)\n",
      "Requirement already satisfied: charset-normalizer<4,>=2 in /opt/conda/lib/python3.11/site-packages (from requests->huggingface-hub>=0.21.0->accelerate) (3.3.2)\n",
      "Requirement already satisfied: idna<4,>=2.5 in /opt/conda/lib/python3.11/site-packages (from requests->huggingface-hub>=0.21.0->accelerate) (3.7)\n",
      "Requirement already satisfied: urllib3<3,>=1.21.1 in /opt/conda/lib/python3.11/site-packages (from requests->huggingface-hub>=0.21.0->accelerate) (2.2.2)\n",
      "Requirement already satisfied: certifi>=2017.4.17 in /opt/conda/lib/python3.11/site-packages (from requests->huggingface-hub>=0.21.0->accelerate) (2024.8.30)\n",
      "Requirement already satisfied: mpmath<1.4,>=1.1.0 in /opt/conda/lib/python3.11/site-packages (from sympy->torch>=2.0.0->accelerate) (1.3.0)\n",
      "Installing collected packages: accelerate\n",
      "Successfully installed accelerate-1.5.2\n",
      "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager, possibly rendering your system unusable.It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv. Use the --root-user-action option if you know what you are doing and want to suppress this warning.\u001b[0m\u001b[33m\n",
      "\u001b[0m"
     ]
    }
   ],
   "source": [
    "!pip install accelerate"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ade2a2a5-bc9b-4db0-a663-1657d7c7bb84",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Some weights of the model checkpoint at embedding_model_small were not used when initializing NewModel: ['classifier.bias', 'classifier.weight']\n",
      "- This IS expected if you are initializing NewModel from the checkpoint of a model trained on another task or with another architecture (e.g. initializing a BertForSequenceClassification model from a BertForPreTraining model).\n",
      "- This IS NOT expected if you are initializing NewModel from the checkpoint of a model that you expect to be exactly identical (initializing a BertForSequenceClassification model from a BertForSequenceClassification model).\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "torch.Size([768])\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/root/.cache/huggingface/modules/transformers_modules/Alibaba-NLP/new-impl/40ced75c3017eb27626c9d4ea981bde21a2662f4/modeling.py:579: UserWarning: 1Torch was not compiled with flash attention. (Triggered internally at /data/jenkins_workspace/workspace/pytorch@4/aten/src/ATen/native/transformers/hip/sdp_utils.cpp:459.)\n",
      "  attn_output = torch.nn.functional.scaled_dot_product_attention(\n",
      "/root/.cache/huggingface/modules/transformers_modules/Alibaba-NLP/new-impl/40ced75c3017eb27626c9d4ea981bde21a2662f4/modeling.py:579: UserWarning: 1Torch was not compiled with memory efficient attention. (Triggered internally at /data/jenkins_workspace/workspace/pytorch@4/aten/src/ATen/native/transformers/hip/sdp_utils.cpp:508.)\n",
      "  attn_output = torch.nn.functional.scaled_dot_product_attention(\n"
     ]
    }
   ],
   "source": [
    "# Requires transformers>=4.36.0\n",
    "\n",
    "import torch.nn.functional as F\n",
    "from transformers import AutoModel, AutoTokenizer\n",
    "import torch\n",
    "\n",
    "input_texts = [\n",
    "    \"what is the capital of China?\",\n",
    "    \"how to implement quick sort in python?\",\n",
    "    \"北京\",\n",
    "    \"快排算法介绍\"\n",
    "]\n",
    "device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n",
    "model_name_or_path = 'embedding_model_small'\n",
    "tokenizer = AutoTokenizer.from_pretrained(model_name_or_path)\n",
    "model = AutoModel.from_pretrained(model_name_or_path, trust_remote_code=True, device_map=\"auto\")\n",
    "\n",
    "# Tokenize the input texts\n",
    "batch_dict = tokenizer(input_texts, max_length=8192, padding=True, truncation=True, return_tensors='pt').to(\"cuda\")\n",
    "outputs = model(**batch_dict)\n",
    "\n",
    "dimension=768 # The output dimension of the output embedding, should be in [128, 768]\n",
    "embeddings = outputs.last_hidden_state[:, 0][:dimension]\n",
    "print(embeddings[0].shape)\n",
    "\n",
    "# [[0.3016996383666992, 0.7503870129585266, 0.3203084468841553]]\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fe2c83a3-512a-4d1d-a214-24d08beefeb4",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 封装成 langchain 可调用的类\n",
    "\n",
    "from typing import List\n",
    "from langchain_core.embeddings import Embeddings\n",
    "import torch\n",
    "from transformers import AutoModel, AutoTokenizer\n",
    "\n",
    "class Embeddings(Embeddings):\n",
    "    def __init__(self):\n",
    "        \"\"\"\n",
    "        先加载模型\n",
    "        \"\"\"          \n",
    "        # 模型下载的本地路径\n",
    "        model_name_or_path = 'embedding_model'\n",
    "        self.tokenizer = AutoTokenizer.from_pretrained(model_name_or_path)\n",
    "        self.model = AutoModel.from_pretrained(model_name_or_path, trust_remote_code=True, device_map=\"auto\")\n",
    "\n",
    "    \n",
    "    def embed_documents(self, texts: List[str]) -> List[List[float]]:\n",
    "        \"\"\"\n",
    "        生成输入文本列表的 embedding.\n",
    "        Args:\n",
    "            texts (List[str]): 要生成 embedding 的文本列表.\n",
    "\n",
    "        Returns:\n",
    "            List[List[float]]: 输入列表中每个文档的 embedding 列表。每个 embedding 都表示为一个浮点值列表。\n",
    "        \"\"\"\n",
    "\n",
    "        result = []\n",
    "        for i in range(0, len(texts), 16):\n",
    "            input_texts = texts[i:i+16]\n",
    "            batch_dict = self.tokenizer(input_texts, max_length=8192, padding=True, truncation=True, return_tensors='pt').to(\"cuda\")\n",
    "            outputs = self.model(**batch_dict)\n",
    "            dimension=768 # The output dimension of the output embedding, should be in [128, 768]\n",
    "            embeddings = outputs.last_hidden_state[:, 0][:dimension]\n",
    "            result.extend([item.cpu().detach().numpy() for item in embeddings])\n",
    "        return result\n",
    "    \n",
    "    def embed_query(self, text: str) -> List[float]:\n",
    "        \"\"\"\n",
    "        生成输入文本的 embedding.\n",
    "\n",
    "        Args:\n",
    "            texts (str): 要生成 embedding 的文本.\n",
    "\n",
    "        Return:\n",
    "            embeddings (List[float]): 输入文本的 embedding，一个浮点数值列表.\n",
    "        \"\"\"\n",
    "        batch_dict = self.tokenizer([text], max_length=8192, padding=True, truncation=True, return_tensors='pt').to(\"cuda\")\n",
    "        outputs = self.model(**batch_dict)\n",
    "        dimension=768 # The output dimension of the output embedding, should be in [128, 768]\n",
    "        embeddings = outputs.last_hidden_state[:, 0][:dimension]\n",
    "        return embeddings[0].cpu().detach().numpy()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5bff97e9-d1e4-4854-b616-10d5889296aa",
   "metadata": {},
   "source": [
    "3. 知识文档处理\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "661d2c3a-8627-410d-b51e-71af3f4109ed",
   "metadata": {},
   "source": [
    "分别下载两个 pdf 文件：\n",
    "\n",
    "- wget https://github.com/datawhalechina/llm-cookbook/releases/download/v1%2C0%2C0/LLM-v1.0.0.pdf\n",
    "- wget https://github.com/datawhalechina/pumpkin-book/releases/download/v2.0.0/pumpkin_book.pdf"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cbb4bacc-32df-4319-980b-7c6c69b81b9a",
   "metadata": {},
   "source": [
    "我们可以使用 LangChain 的 PyMuPDFLoader 来读取知识库的 PDF 文件。PyMuPDFLoader 是 PDF 解析器中速度最快的一种，结果会包含 PDF 及其页面的详细元数据，并且每页返回一个文档。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "c2ee53c0-e7f2-4f7f-82b9-65b43f01671c",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "huggingface/tokenizers: The current process just got forked, after parallelism has already been used. Disabling parallelism to avoid deadlocks...\n",
      "To disable this warning, you can either:\n",
      "\t- Avoid using `tokenizers` before the fork if possible\n",
      "\t- Explicitly set the environment variable TOKENIZERS_PARALLELISM=(true | false)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple\n",
      "Collecting pymupdf\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/36/ae/9b3651d457698ff5e19c5a663c51703cc990892b35cf4a779c36a1a1bf64/pymupdf-1.25.4-cp39-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (20.0 MB)\n",
      "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m20.0/20.0 MB\u001b[0m \u001b[31m29.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0ma \u001b[36m0:00:01\u001b[0m\n",
      "\u001b[?25hInstalling collected packages: pymupdf\n",
      "Successfully installed pymupdf-1.25.4\n",
      "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager, possibly rendering your system unusable.It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv. Use the --root-user-action option if you know what you are doing and want to suppress this warning.\u001b[0m\u001b[33m\n",
      "\u001b[0m"
     ]
    }
   ],
   "source": [
    "!pip3 install pymupdf"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5a1e993a-cb4e-4415-a5e0-7db5f5706c9a",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 使用 langchain 自带的 loader 读取\n",
    "from langchain_community.document_loaders import PyMuPDFLoader\n",
    "import os\n",
    "\n",
    "# 存储路径\n",
    "pdf_file = \"/pdf/LLM-v1.0.0.pdf\"\n",
    "\n",
    "# 创建一个 PyMuPDFLoader Class 实例，输入为待加载的 pdf 文档路径\n",
    "loader = PyMuPDFLoader(pdf_file)\n",
    "\n",
    "# 调用 PyMuPDFLoader Class 的函数 load 对 pdf 文件进行加载\n",
    "pdf_pages = loader.load()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b4e00330-787c-4683-98ed-898a9df979e3",
   "metadata": {},
   "source": [
    "文档加载后储存在 pages 变量中:\n",
    "\n",
    "- page 的变量类型为 List\n",
    "- 打印 pages 的长度可以看到 pdf 一共包含多少页"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "228a6a0c-ae00-4e85-873e-d4d170cece18",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "载入后的变量类型为：<class 'list'>， 该 PDF 一共包含 373 页\n"
     ]
    }
   ],
   "source": [
    "print(f\"载入后的变量类型为：{type(pdf_pages)}，\",  f\"该 PDF 一共包含 {len(pdf_pages)} 页\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1235efa3-0f9e-4f9d-99e1-d5d547862b75",
   "metadata": {},
   "source": [
    "page 中的每一元素为一个文档，变量类型为 langchain_core.documents.base.Document, 文档变量类型包含两个属性\n",
    "\n",
    "- page_content 包含该文档的内容。\n",
    "- meta_data 为文档相关的描述性数据。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "a83a7b39-fa01-4805-8861-ff1865b093ca",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "每一个元素的类型：<class 'langchain_core.documents.base.Document'>.\n",
      "------\n",
      "该文档的描述性数据：{'source': '/root/private_data/zyh/data/base_data/pdf/LLM-v1.0.0.pdf', 'file_path': '/root/private_data/zyh/data/base_data/pdf/LLM-v1.0.0.pdf', 'page': 10, 'total_pages': 373, 'format': 'PDF 1.7', 'title': '', 'author': '', 'subject': '', 'keywords': '', 'creator': '', 'producer': 'iLovePDF', 'creationDate': '', 'modDate': 'D:20230817062022Z', 'trapped': ''}\n",
      "------\n",
      "查看该文档的内容:\n",
      "第二章 提示原则\n",
      " \n",
      "如何去使用 Prompt，以充分发挥 LLM 的性能？首先我们需要知道设计 Prompt 的原则，它们是每一个\n",
      "开发者设计 Prompt 所必须知道的基础概念。本章讨论了设计高效 Prompt 的两个关键原则：编写清\n",
      "晰、具体的指令和给予模型充足思考时间。掌握这两点，对创建可靠的语言模型交互尤为重要。\n",
      "首先，Prompt 需要清晰明确地表达需求，提供充足上下文，使语言模型准确理解我们的意图，就像向一\n",
      "个外星人详细解释人类世界一样。过于简略的 Prompt 往往使模型难以把握所要完成的具体任务。\n",
      "其次，让语言模型有充足时间推理也极为关键。就像人类解题一样，匆忙得出的结论多有失误。因此 \n",
      "Prompt 应加入逐步推理的要求，给模型留出充分思考时间，这样生成的结果才更准确可靠。\n",
      "如果 Prompt 在这两点上都作了优化，语言模型就能够尽可能发挥潜力，完成复杂的推理和生成任务。\n",
      "掌握这些 Prompt 设计原则，是开发者取得语言模型应用成功的重要一步。\n",
      "一、原则一 编写清晰、具体的指令\n",
      " \n",
      "亲爱的读者，在与语言模型交互时，您需要牢记一点:以清晰、具体的方式表达您的需求。假设您面前坐\n",
      "着一位来自外星球的新朋友，其对人类语言和常识都一无所知。在这种情况下，您需要把想表达的意图\n",
      "讲得非常明确，不要有任何歧义。同样的，在提供 Prompt 的时候，也要以足够详细和容易理解的方\n",
      "式，把您的需求与上下文说清楚。 \n",
      "并不是说 Prompt 就必须非常短小简洁。事实上，在许多情况下，更长、更复杂的 Prompt 反而会让语\n",
      "言模型更容易抓住关键点，给出符合预期的回复。原因在于，复杂的 Prompt 提供了更丰富的上下文和\n",
      "细节，让模型可以更准确地把握所需的操作和响应方式。\n",
      "所以，记住用清晰、详尽的语言表达 Prompt，就像在给外星人讲解人类世界一样，“Adding more \n",
      "context helps the model understand you better.”。\n",
      "从该原则出发，我们提供几个设计 Prompt 的技巧。\n",
      "1.1 使用分隔符清晰地表示输入的不同部分\n",
      " \n",
      "在编写 Prompt 时，我们可以使用各种标点符号作为“分隔符”，将不同的文本部分区分开来。\n",
      "分隔符就像是 Prompt 中的墙，将不同的指令、上下文、输入隔开，避免意外的混淆。你可以选择用 \n",
      "```，\"\"\"，< >，<tag> </tag>，:  等做分隔符，只要能明确起到隔断作用即可。\n",
      "使用分隔符尤其重要的是可以防止 提示词注入（Prompt Rejection）。什么是提示词注入？就是用户\n",
      "输入的文本可能包含与你的预设 Prompt 相冲突的内容，如果不加分隔，这些输入就可能“注入”并操纵语\n",
      "言模型，导致模型产生毫无关联的乱七八糟的输出。\n",
      "在以下的例子中，我们给出一段话并要求 GPT 进行总结，在该示例中我们使用 ``` 来作为分隔符。\n",
      "from tool import get_completion\n",
      "text = f\"\"\"\n",
      "您应该提供尽可能清晰、具体的指示，以表达您希望模型执行的任务。\\\n",
      "这将引导模型朝向所需的输出，并降低收到无关或不正确响应的可能性。\\\n",
      "不要将写清晰的提示词与写简短的提示词混淆。\\\n",
      "在许多情况下，更长的提示词可以为模型提供更多的清晰度和上下文信息，从而导致更详细和相关的输出。\n",
      "\"\"\"\n",
      "# 需要总结的文本内容\n",
      "prompt = f\"\"\"\n",
      "把用三个反引号括起来的文本总结成一句话。\n",
      "\n"
     ]
    }
   ],
   "source": [
    "pdf_page = pdf_pages[10]\n",
    "print(f\"每一个元素的类型：{type(pdf_page)}.\", \n",
    "    f\"该文档的描述性数据：{pdf_page.metadata}\", \n",
    "    f\"查看该文档的内容:\\n{pdf_page.page_content}\", \n",
    "    sep=\"\\n------\\n\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3d35f032-e53a-435f-84bd-dd0e9d25fe79",
   "metadata": {},
   "source": [
    "由于单个文档的长度往往会超过模型支持的上下文，导致检索得到的知识太长超出模型的处理能力，因此，在构建向量知识库的过程中，我们往往需要对文档进行分割，将单个文档按长度或者按固定的规则分割成若干个 chunk，然后将每个 chunk 转化为词向量，存储到向量数据库中。\n",
    "\n",
    "在检索时，我们会以 chunk 作为检索的元单位，也就是每一次检索到 k 个 chunk 作为模型可以参考来回答用户问题的知识，这个 k 是我们可以自由设定的。\n",
    "\n",
    "Langchain 中文本分割器都根据 chunk_size (块大小)和 chunk_overlap (块与块之间的重叠大小)进行分割:\n",
    "\n",
    "- chunk_size 指每个块包含的字符或 Token （如单词、句子等）的数量\n",
    "- chunk_overlap 指两个块之间共享的字符数量，用于保持上下文的连贯性，避免分割丢失上下文信息\n",
    "\n",
    "Langchain 提供多种文档分割方式，区别在怎么确定块与块之间的边界、块由哪些字符/token组成、以及如何测量块大小。这里我们使用最常用的分割器：\n",
    "\n",
    "RecursiveCharacterTextSplitter(): 按字符串分割文本，递归地尝试按不同的分隔符进行分割文本。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "0282c677-258d-41cd-a639-555a55d69f8d",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['第二章 提示原则\\n \\n如何去使用 Prompt，以充分发挥 LLM 的性能？首先我们需要知道设计 Prompt 的原则，它们是每一个\\n开发者设计 Prompt 所必须知道的基础概念。本章讨论了设计高效 Prompt 的两个关键原则：编写清\\n晰、具体的指令和给予模型充足思考时间。掌握这两点，对创建可靠的语言模型交互尤为重要。\\n首先，Prompt 需要清晰明确地表达需求，提供充足上下文，使语言模型准确理解我们的意图，就像向一\\n个外星人详细解释人类世界一样。过于简略的 Prompt 往往使模型难以把握所要完成的具体任务。\\n其次，让语言模型有充足时间推理也极为关键。就像人类解题一样，匆忙得出的结论多有失误。因此 \\nPrompt 应加入逐步推理的要求，给模型留出充分思考时间，这样生成的结果才更准确可靠。\\n如果 Prompt 在这两点上都作了优化，语言模型就能够尽可能发挥潜力，完成复杂的推理和生成任务。\\n掌握这些 Prompt 设计原则，是开发者取得语言模型应用成功的重要一步。\\n一、原则一 编写清晰、具体的指令',\n",
       " '一、原则一 编写清晰、具体的指令\\n \\n亲爱的读者，在与语言模型交互时，您需要牢记一点:以清晰、具体的方式表达您的需求。假设您面前坐\\n着一位来自外星球的新朋友，其对人类语言和常识都一无所知。在这种情况下，您需要把想表达的意图\\n讲得非常明确，不要有任何歧义。同样的，在提供 Prompt 的时候，也要以足够详细和容易理解的方\\n式，把您的需求与上下文说清楚。 \\n并不是说 Prompt 就必须非常短小简洁。事实上，在许多情况下，更长、更复杂的 Prompt 反而会让语\\n言模型更容易抓住关键点，给出符合预期的回复。原因在于，复杂的 Prompt 提供了更丰富的上下文和\\n细节，让模型可以更准确地把握所需的操作和响应方式。\\n所以，记住用清晰、详尽的语言表达 Prompt，就像在给外星人讲解人类世界一样，“Adding more \\ncontext helps the model understand you better.”。\\n从该原则出发，我们提供几个设计 Prompt 的技巧。\\n1.1 使用分隔符清晰地表示输入的不同部分',\n",
       " '1.1 使用分隔符清晰地表示输入的不同部分\\n \\n在编写 Prompt 时，我们可以使用各种标点符号作为“分隔符”，将不同的文本部分区分开来。\\n分隔符就像是 Prompt 中的墙，将不同的指令、上下文、输入隔开，避免意外的混淆。你可以选择用']"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "''' \n",
    "* RecursiveCharacterTextSplitter 递归字符文本分割\n",
    "RecursiveCharacterTextSplitter 将按不同的字符递归地分割(按照这个优先级[\"\\n\\n\", \"\\n\", \" \", \"\"])，\n",
    "    这样就能尽量把所有和语义相关的内容尽可能长时间地保留在同一位置\n",
    "RecursiveCharacterTextSplitter需要关注的是4个参数：\n",
    "\n",
    "* separators - 分隔符字符串数组\n",
    "* chunk_size - 每个文档的字符数量限制\n",
    "* chunk_overlap - 两份文档重叠区域的长度\n",
    "* length_function - 长度计算函数\n",
    "'''\n",
    "#导入文本分割器\n",
    "from langchain_text_splitters import RecursiveCharacterTextSplitter\n",
    "\n",
    "# 知识库中单段文本长度\n",
    "CHUNK_SIZE = 500\n",
    "\n",
    "# 知识库中相邻文本重合长度\n",
    "OVERLAP_SIZE = 50\n",
    "\n",
    "# 使用递归字符文本分割器\n",
    "text_splitter = RecursiveCharacterTextSplitter(\n",
    "    chunk_size=CHUNK_SIZE,\n",
    "    chunk_overlap=OVERLAP_SIZE\n",
    ")\n",
    "text_splitter.split_text(pdf_page.page_content[0:1000])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "561f9e39-33a8-4e3a-9ba4-6f9651603bc1",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "切分后的文件数量：1281\n"
     ]
    }
   ],
   "source": [
    "split_docs = text_splitter.split_documents(pdf_pages)\n",
    "print(f\"切分后的文件数量：{len(split_docs)}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "96c85d52-1c01-4746-95f1-ff2d1d03f8e3",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "切分后的字符数（可以用来大致评估 token 数）：523817\n"
     ]
    }
   ],
   "source": [
    "print(f\"切分后的字符数（可以用来大致评估 token 数）：{sum([len(doc.page_content) for doc in split_docs])}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "250a1cbe-77ae-4bd6-9c7d-f66fd6f2c42d",
   "metadata": {},
   "source": [
    "注：如何对文档进行分割，其实是数据处理中最核心的一步，其往往决定了检索系统的下限。但是，如何选择分割方式，往往具有很强的业务相关性——针对不同的业务、不同的源数据，往往需要设定个性化的文档分割方式。因此，在该部分，我们仅简单根据 chunk_size 对文档进行分割。后续在 RAG 应用的优化环节，我们会进一步探究如何优化文档的处理及分割从而提高 RAG 系统的检索精度和回答性能。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fde1f841-bc23-415b-9d65-f39a1c845fd2",
   "metadata": {},
   "source": [
    "4. 构建向量知识库"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "e7f01c94-25df-4678-8aa9-fbe2e0a32606",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['data/base_data/pdf/LLM-v1.0.0.pdf', 'data/base_data/pdf/pumpkin_book.pdf']\n"
     ]
    }
   ],
   "source": [
    "# 获取 folder_path 下所有文件路径，储存在 file_paths 里\n",
    "import os\n",
    "file_paths = []\n",
    "folder_path = 'data/base_data/pdf'\n",
    "files = os.listdir(folder_path)\n",
    "for file in files:\n",
    "    # 忽略隐藏文件\n",
    "    if file[0] == \".\": continue\n",
    "    file_path = os.path.join(folder_path, file)\n",
    "    file_paths.append(file_path)\n",
    "print(file_paths)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "e8d6dc0f-7966-45fe-b717-0164e3227d76",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from langchain_community.document_loaders import PyMuPDFLoader\n",
    "\n",
    "# 遍历文件路径并把实例化的loader存放在loaders里\n",
    "loaders = []\n",
    "\n",
    "for file_path in file_paths:\n",
    "    file_type = file_path.split('.')[-1]\n",
    "    if file_type == 'pdf':\n",
    "        loaders.append(PyMuPDFLoader(file_path))\n",
    "\n",
    "len(loaders)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "4e0e0c0b-fb51-4ead-9053-e923d95296a4",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "569"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 下载文件并存储到text\n",
    "texts = []\n",
    "\n",
    "for loader in loaders: \n",
    "    texts.extend(loader.load())\n",
    "\n",
    "len(texts)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "4562846b-14ce-424d-899e-d9ceafa2a7be",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "每一个元素的类型：<class 'langchain_core.documents.base.Document'>.\n",
      "------\n",
      "该文档的描述性数据：{'source': 'data/base_data/pdf/LLM-v1.0.0.pdf', 'file_path': 'data/base_data/pdf/LLM-v1.0.0.pdf', 'page': 1, 'total_pages': 373, 'format': 'PDF 1.7', 'title': '', 'author': '', 'subject': '', 'keywords': '', 'creator': '', 'producer': 'iLovePDF', 'creationDate': '', 'modDate': 'D:20230817062022Z', 'trapped': ''}\n",
      "------\n",
      "查看该文档的内容:\n",
      "7. 文本扩展 Expanding @邹雨衡\n",
      "8. 聊天机器人 Chatbot @长琴\n",
      "9. 总结 @长琴\n",
      "附1 使用 ChatGLM 进行学习 @宋志学\n",
      "二、搭建基于 ChatGPT 的问答系统\n",
      " \n",
      " 注：吴恩达《Building Systems with the ChatGPT API》课程中文版\n",
      " 目录：\n",
      "1. 简介 Introduction @Sarai\n",
      "2. 模型，范式和 token Language Models, the Chat Format and Tokens @仲泰\n",
      "3. 检查输入-分类 Classification @诸世纪\n",
      "4. 检查输入-监督 Moderation @诸世纪\n",
      "5. 思维链推理 Chain of Thought Reasoning @万礼行\n",
      "6. 提示链 Chaining Prompts @万礼行\n",
      "7. 检查输入 Check Outputs @仲泰\n",
      "8. 评估（端到端系统）Evaluation @邹雨衡\n",
      "9. 评估（简单问答）Evaluation-part1 @陈志宏、邹雨衡\n",
      "10. 评估（复杂问答）Evaluation-part2 @邹雨衡\n",
      "11. 总结 Conclusion @Sarai\n",
      "三、使用 LangChain 开发应用程序\n",
      " \n",
      " 注：吴恩达《LangChain for LLM Application Development》课程中文版\n",
      " 目录：\n",
      "1. 简介 Introduction @Sarai\n",
      "2. 模型，提示和解析器 Models, Prompts and Output Parsers @Joye\n",
      "3. 存储 Memory @徐虎\n",
      "4. 模型链 Chains @徐虎\n",
      "5. 基于文档的问答 Question and Answer @苟晓攀\n",
      "6. 评估 Evaluation @苟晓攀\n",
      "7. 代理 Agent @Joye\n",
      "8. 总结 Conclusion @Sarai\n",
      "四、使用 LangChain 访问个人数据\n",
      " \n",
      " 注：吴恩达《LangChain Chat with Your Data》课程中文版\n",
      " 目录：\n",
      "1. 简介 Introduction @Joye\n",
      "2. 加载文档 Document Loading @Joye\n",
      "3. 文档切割 Document Splitting @苟晓攀\n",
      "\n"
     ]
    }
   ],
   "source": [
    "text = texts[1]\n",
    "print(f\"每一个元素的类型：{type(text)}.\", \n",
    "    f\"该文档的描述性数据：{text.metadata}\", \n",
    "    f\"查看该文档的内容:\\n{text.page_content[0:]}\", \n",
    "    sep=\"\\n------\\n\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "0d05ed03-fbba-49b1-b2ee-5fecbcca477e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1995"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from langchain_text_splitters import RecursiveCharacterTextSplitter\n",
    "\n",
    "# 切分文档\n",
    "text_splitter = RecursiveCharacterTextSplitter(\n",
    "    chunk_size=500, chunk_overlap=50)\n",
    "\n",
    "split_docs = text_splitter.split_documents(texts)\n",
    "len(split_docs)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "ce2c4c27-2901-467b-bedb-2256b95b5fe0",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "WARNING[XFORMERS]: xFormers can't load C++/CUDA extensions. xFormers was built for:\n",
      "    PyTorch 2.1.0 with CUDA None (you have 2.3.0)\n",
      "    Python  3.11.9 (you have 3.11.9)\n",
      "  Please reinstall xformers (see https://github.com/facebookresearch/xformers#installing-xformers)\n",
      "  Memory-efficient attention, SwiGLU, sparse and more won't be available.\n",
      "  Set XFORMERS_MORE_DETAILS=1 for more details\n",
      "Some weights of the model checkpoint at embedding_model_small were not used when initializing NewModel: ['classifier.bias', 'classifier.weight']\n",
      "- This IS expected if you are initializing NewModel from the checkpoint of a model trained on another task or with another architecture (e.g. initializing a BertForSequenceClassification model from a BertForPreTraining model).\n",
      "- This IS NOT expected if you are initializing NewModel from the checkpoint of a model that you expect to be exactly identical (initializing a BertForSequenceClassification model from a BertForSequenceClassification model).\n",
      "/root/.cache/huggingface/modules/transformers_modules/Alibaba-NLP/new-impl/40ced75c3017eb27626c9d4ea981bde21a2662f4/modeling.py:579: UserWarning: 1Torch was not compiled with flash attention. (Triggered internally at /data/jenkins_workspace/workspace/pytorch@4/aten/src/ATen/native/transformers/hip/sdp_utils.cpp:459.)\n",
      "  attn_output = torch.nn.functional.scaled_dot_product_attention(\n",
      "/root/.cache/huggingface/modules/transformers_modules/Alibaba-NLP/new-impl/40ced75c3017eb27626c9d4ea981bde21a2662f4/modeling.py:579: UserWarning: 1Torch was not compiled with memory efficient attention. (Triggered internally at /data/jenkins_workspace/workspace/pytorch@4/aten/src/ATen/native/transformers/hip/sdp_utils.cpp:508.)\n",
      "  attn_output = torch.nn.functional.scaled_dot_product_attention(\n",
      "/tmp/ipykernel_7993/1400556994.py:16: LangChainDeprecationWarning: Since Chroma 0.4.x the manual persistence method is no longer supported as docs are automatically persisted.\n",
      "  vectordb.persist()\n"
     ]
    }
   ],
   "source": [
    "# 使用 chroma 构建向量数据库\n",
    "from langchain_community.vectorstores import Chroma\n",
    "\n",
    "# 定义 Embeddings\n",
    "embedding = Embeddings()\n",
    "\n",
    "# 定义持久化路径\n",
    "persist_directory = 'data/chroma'\n",
    "\n",
    "vectordb = Chroma.from_documents(\n",
    "    documents=split_docs,\n",
    "    embedding=embedding,\n",
    "    persist_directory=persist_directory  # 允许我们将persist_directory目录保存到磁盘上\n",
    ")\n",
    "\n",
    "vectordb.persist()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "f6b90e1c-2952-45b8-9471-0add6bf7251b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "向量库中存储的数量：1995\n"
     ]
    }
   ],
   "source": [
    "print(f\"向量库中存储的数量：{vectordb._collection.count()}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "31f7b2e1-5788-42ee-abef-9e7c7c9d6db2",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/tmp/ipykernel_8369/2233374908.py:2: LangChainDeprecationWarning: Since Chroma 0.4.x the manual persistence method is no longer supported as docs are automatically persisted.\n",
      "  vectordb.persist()\n"
     ]
    }
   ],
   "source": [
    "# 持久化向量库\n",
    "vectordb.persist()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "7ff47a5d-9165-45ac-aae9-f1daba3da825",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "检索到的内容数：3\n",
      "检索到的第0个内容: \n",
      "\u0001本\u0003:2.0.0\n",
      "发布日期:2023.11\n",
      "南  ⽠  书\n",
      "PUMPKIN\n",
      "B  O  O  K\n",
      "谢\t睿 \u000b\n",
      "州 贾彬彬\n",
      "--------------\n",
      "检索到的第1个内容: \n",
      "最新版PDF 获取地址：https://github.com/datawhalechina/pumpkin-book/releases\n",
      "编委会\n",
      "主编：Sm1les、archwalker、jbb0523\n",
      "编委：juxiao、Majingmin、MrBigFan、shanry、Ye980226\n",
      "封面设计：构思-Sm1les、创作-林王茂盛\n",
      "致谢\n",
      "特别感谢awyd234、feijuan、Ggmatch、Heitao5200、huaqing89、LongJH、LilRachel、LeoLRH、Nono17、\n",
      "spareribs、sunchaothu、StevenLzq 在最早期的时候对南瓜书所做的贡献。\n",
      "扫描下方二维码，然后回复关键词“南瓜书”，即可加入“南瓜书读者交流群”\n",
      "版权声明\n",
      "本作品采用知识共享署名-非商业性使用-相同方式共享4.0 国际许可协议进行许可。\n",
      "--------------\n",
      "检索到的第2个内容: \n",
      "前言\n",
      "“周志华老师的《机器学习》（西瓜书）是机器学习领域的经典入门教材之一，周老师为了使尽可能多的读\n",
      "者通过西瓜书对机器学习有所了解, 所以在书中对部分公式的推导细节没有详述，但是这对那些想深究公式推\n",
      "导细节的读者来说可能“不太友好”，本书旨在对西瓜书里比较难理解的公式加以解析，以及对部分公式补充\n",
      "具体的推导细节。”\n",
      "读到这里，大家可能会疑问为啥前面这段话加了引号，因为这只是我们最初的遐想，后来我们了解到，周\n",
      "老师之所以省去这些推导细节的真实原因是，他本尊认为“理工科数学基础扎实点的大二下学生应该对西瓜书\n",
      "中的推导细节无困难吧，要点在书里都有了，略去的细节应能脑补或做练习”。所以...... 本南瓜书只能算是我\n",
      "等数学渣渣在自学的时候记下来的笔记，希望能够帮助大家都成为一名合格的“理工科数学基础扎实点的大二\n",
      "下学生”。\n",
      "使用说明\n",
      "• 南瓜书的所有内容都是以西瓜书的内容为前置知识进行表述的，所以南瓜书的最佳使用方法是以西瓜书\n",
      "为主线，遇到自己推导不出来或者看不懂的公式时再来查阅南瓜书；\n",
      "• 对于初学机器学习的小白，西瓜书第1 章和第2 章的公式强烈不建议深究，简单过一下即可，等你学得\n",
      "--------------\n"
     ]
    }
   ],
   "source": [
    "# 测试一下向量检索\n",
    "\n",
    "question=\"什么是南瓜书\"\n",
    "sim_docs = vectordb.similarity_search(question,k=3)\n",
    "print(f\"检索到的内容数：{len(sim_docs)}\")\n",
    "for i, sim_doc in enumerate(sim_docs):\n",
    "    print(f\"检索到的第{i}个内容: \\n{sim_doc.page_content}\", end=\"\\n--------------\\n\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9932360c-0c83-4276-9c7f-3bac79ea15e3",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 封装成一个检索器\n",
    "def get_retriever():\n",
    "    # 定义 Embeddings\n",
    "    embedding = Embeddings()\n",
    "    # 向量数据库持久化路径\n",
    "    persist_directory = 'data/chroma'\n",
    "    # 加载数据库\n",
    "    vectordb = Chroma(\n",
    "        persist_directory=persist_directory,\n",
    "        embedding_function=embedding\n",
    "    )\n",
    "    return vectordb.as_retriever()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5e03bbc8-accf-4762-bf3f-0a3f1b06f648",
   "metadata": {},
   "source": [
    "5. 构建 RAG 链路"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6e491b55-6d28-418a-a77e-e85fd57611fc",
   "metadata": {},
   "source": [
    "使用 LangChain 构建 RAG 链路"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "925d5d14-7c98-4678-b7ad-8aac3db073c0",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/tmp/ipykernel_2542/1517970404.py:8: LangChainDeprecationWarning: The class `Chroma` was deprecated in LangChain 0.2.9 and will be removed in 1.0. An updated version of the class exists in the langchain-chroma package and should be used instead. To use it run `pip install -U langchain-chroma` and import as `from langchain_chroma import Chroma`.\n",
      "  vectordb = Chroma(\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'前言\\n“周志华老师的《机器学习》（西瓜书）是机器学习领域的经典入门教材之一，周老师为了使尽可能多的读\\n者通过西瓜书对机器学习有所了解, 所以在书中对部分公式的推导细节没有详述，但是这对那些想深究公式推\\n导细节的读者来说可能“不太友好”，本书旨在对西瓜书里比较难理解的公式加以解析，以及对部分公式补充\\n具体的推导细节。”\\n读到这里，大家可能会疑问为啥前面这段话加了引号，因为这只是我们最初的遐想，后来我们了解到，周\\n老师之所以省去这些推导细节的真实原因是，他本尊认为“理工科数学基础扎实点的大二下学生应该对西瓜书\\n中的推导细节无困难吧，要点在书里都有了，略去的细节应能脑补或做练习”。所以...... 本南瓜书只能算是我\\n等数学渣渣在自学的时候记下来的笔记，希望能够帮助大家都成为一名合格的“理工科数学基础扎实点的大二\\n下学生”。\\n使用说明\\n• 南瓜书的所有内容都是以西瓜书的内容为前置知识进行表述的，所以南瓜书的最佳使用方法是以西瓜书\\n为主线，遇到自己推导不出来或者看不懂的公式时再来查阅南瓜书；\\n• 对于初学机器学习的小白，西瓜书第1 章和第2 章的公式强烈不建议深究，简单过一下即可，等你学得\\n\\n最新版PDF 获取地址：https://github.com/datawhalechina/pumpkin-book/releases\\n编委会\\n主编：Sm1les、archwalker、jbb0523\\n编委：juxiao、Majingmin、MrBigFan、shanry、Ye980226\\n封面设计：构思-Sm1les、创作-林王茂盛\\n致谢\\n特别感谢awyd234、feijuan、Ggmatch、Heitao5200、huaqing89、LongJH、LilRachel、LeoLRH、Nono17、\\nspareribs、sunchaothu、StevenLzq 在最早期的时候对南瓜书所做的贡献。\\n扫描下方二维码，然后回复关键词“南瓜书”，即可加入“南瓜书读者交流群”\\n版权声明\\n本作品采用知识共享署名-非商业性使用-相同方式共享4.0 国际许可协议进行许可。\\n\\n\\x01本\\x03:2.0.0\\n发布日期:2023.11\\n南  ⽠  书\\nPUMPKIN\\nB  O  O  K\\n谢\\t睿 \\x0b州 贾彬彬\\n\\n• 对于初学机器学习的小白，西瓜书第1 章和第2 章的公式强烈不建议深究，简单过一下即可，等你学得\\n有点飘的时候再回来啃都来得及；\\n• 每个公式的解析和推导我们都力(zhi) 争(neng) 以本科数学基础的视角进行讲解，所以超纲的数学知识\\n我们通常都会以附录和参考文献的形式给出，感兴趣的同学可以继续沿着我们给的资料进行深入学习；\\n• 若南瓜书里没有你想要查阅的公式，或者你发现南瓜书哪个地方有错误，请毫不犹豫地去我们GitHub 的\\nIssues（地址：https://github.com/datawhalechina/pumpkin-book/issues）进行反馈，在对应版块\\n提交你希望补充的公式编号或者勘误信息，我们通常会在24 小时以内给您回复，超过24 小时未回复的\\n话可以微信联系我们（微信号：at-Sm1les）；\\n配套视频教程：https://www.bilibili.com/video/BV1Mh411e7VU\\n在线阅读地址：https://datawhalechina.github.io/pumpkin-book（仅供第1 版）'"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 先构建一个检索链\n",
    "from langchain_core.runnables import RunnableLambda\n",
    "\n",
    "def combine_docs(docs):\n",
    "    return \"\\n\\n\".join(doc.page_content for doc in docs)\n",
    "\n",
    "retriever = get_retriever()\n",
    "combiner = RunnableLambda(combine_docs)\n",
    "retrieval_chain = retriever | combiner\n",
    "\n",
    "retrieval_chain.invoke(\"南瓜书是什么？\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "0d923f37-c9c5-4cd7-a4a7-10c68419de80",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_core.prompts import PromptTemplate\n",
    "from langchain_core.runnables import RunnablePassthrough, RunnableParallel\n",
    "from langchain_core.output_parsers import StrOutputParser\n",
    "\n",
    "template = \"\"\"\n",
    "参考给定的知识，回答用户的问题。\n",
    "你可以结合给定知识进行适当推理，但务必准确。\n",
    "回答用户问题时，你需要给出你的参考依据。\n",
    "可参考的知识：\n",
    "```\n",
    "{context}\n",
    "```\n",
    "需要回答的用户问题: {input}\n",
    "\"\"\"\n",
    "\n",
    "# 将template通过 PromptTemplate 转为可以在LCEL中使用的类型\n",
    "prompt = PromptTemplate(template=template)\n",
    "\n",
    "qa_chain = (\n",
    "    RunnableParallel({\"context\": retrieval_chain, \"input\": RunnablePassthrough()})\n",
    "    | prompt\n",
    "    | llm\n",
    "    | StrOutputParser()\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "da1371b1-07d7-4f45-aec0-b6ab843abe0f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "大模型+知识库后回答 question_1 的结果：\n",
      "<think>\n",
      "好的，我需要回答用户的问题：“什么是南瓜书？”首先，我会查看提供的知识内容，寻找与南瓜书相关的信息。\n",
      "\n",
      "在知识中，南瓜书被提到是周志华《机器学习》（西瓜书）的补充解析，专注于解析书中的公式和推导细节。编委会和编委的信息显示，南瓜书是由Sm1les、archwalker、jbb0523等主编，还有其他编委和贡献者。南瓜书的版权信息和获取方式也提到了GitHub地址和纸质版的购买渠道。\n",
      "\n",
      "此外，南瓜书的使用说明建议用户以西瓜书为主线，遇到困难时查阅南瓜书。还提到了致谢部分，感谢早期贡献者，并说明南瓜书的内容是基于西瓜书的前置知识进行的。南瓜书还有配套的视频教程和在线阅读地址。\n",
      "\n",
      "综合以上信息，南瓜书是一个开源项目，旨在帮助读者深入理解西瓜书中的公式和推导，适合数学基础较弱的自学读者。因此，回答应涵盖南瓜书的定义、内容、编委会、获取方式和使用建议等方面。\n",
      "</think>\n",
      "\n",
      "南瓜书是《机器学习公式详解》的别称，由国内社区DataWhale组织编写，旨在帮助读者深入理解周志华《机器学习》（西瓜书）中的公式和推导细节。以下是关于南瓜书的详细介绍：\n",
      "\n",
      "1. **定义与目的**：\n",
      "   - 南瓜书是对西瓜书中较难理解公式的解析和补充推导，特别适合数学基础较弱的读者。\n",
      "\n",
      "2. **编委会与贡献者**：\n",
      "   - 主编：Sm1les、archwalker、jbb0523。\n",
      "   - 编委：juxiao、Majingmin、MrBigFan、shanry、Ye980226。\n",
      "   - 其他贡献者包括awyd234、feijuan、Ggmatch等。\n",
      "\n",
      "3. **获取方式**：\n",
      "   - 最新版PDF可在GitHub获取：https://github.com/datawhalechina/pumpkin-book/releases。\n",
      "   - 纸质版可在各大电商平台选购。\n",
      "\n",
      "4. **使用说明**：\n",
      "   - 以西瓜书为主线，遇到推导困难时查阅南瓜书。\n",
      "   - 对于初学机器学习的小白，建议先简单过一遍西瓜书的前两章。\n",
      "\n",
      "5. **版权与致谢**：\n",
      "   - 使用知识共享署名-非商业性使用-相同方式共享4.0国际许可协议。\n",
      "   - 感谢早期贡献者和社区支持。\n",
      "\n",
      "6. **配套资源**：\n",
      "   - 视频教程：B站视频BV1Mh411e7VU。\n",
      "   - 在线阅读：https://datawhalechina.github.io/pumpkin-book（仅供第1版）。\n",
      "\n",
      "南瓜书是一个开源项目，读者可参与贡献，帮助完善内容。任何反馈或勘误可通过GitHub Issues或联系微信号at-Sm1les提交。\n",
      "\n",
      "大模型直接回答 question_1 的结果：\n",
      "<think>\n",
      "好的，我需要回答关于“南瓜书”的问题。首先，南瓜书可能是一个翻译错误，正确的应该是“南瓜饼”。南瓜饼在中文里特指什么？可能是指南瓜做的甜点，比如南瓜饼或者南瓜派。\n",
      "\n",
      "接下来，南瓜饼通常用南瓜泥制作，加入糖、黄油、香料等，烤制而成。在美国，南瓜派是感恩节的传统甜点，非常受欢迎。在中国，南瓜饼可能有不同的做法，比如用糯米粉包裹南瓜馅，蒸熟后食用，口感软糯。\n",
      "\n",
      "另外，南瓜书可能是指以南瓜为主题的书，但可能性较小。考虑到常见的表达方式，南瓜饼更有可能是指食物。因此，我需要解释南瓜饼的定义、制作方法、常见配料以及在不同文化中的表现。\n",
      "\n",
      "最后，总结南瓜饼的特点，强调它在不同文化中的地位和受欢迎程度，确保回答全面且易于理解。\n",
      "</think>\n",
      "\n",
      "南瓜书可能是一个不太常见的表达方式，可能是对某种特定书籍的称呼，或者是某种翻译或转译的结果。如果你指的是某种特定的书籍或概念，请提供更多的上下文信息，这样我可以更准确地帮助你解答。如果你是想了解南瓜相关的书籍或内容，南瓜通常与万圣节、秋天的装饰以及一些美食（如南瓜派）相关联，可能有一些书籍涉及这些主题。如果你能提供更多的信息，我会尽力帮助你找到答案。\n"
     ]
    }
   ],
   "source": [
    "# 测试效果\n",
    "\n",
    "question_1 = \"什么是南瓜书？\"\n",
    "\n",
    "result = qa_chain.invoke(question_1)\n",
    "print(\"大模型+知识库后回答 question_1 的结果：\")\n",
    "print(result)\n",
    "print()\n",
    "\n",
    "result = llm.invoke(question_1)\n",
    "print(\"大模型直接回答 question_1 的结果：\")\n",
    "print(result)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8c324a70-588c-425f-a539-39365e9eb97f",
   "metadata": {},
   "source": [
    "6. 构建带历史记录的 RAG 链路"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "58e74e6f-fd7f-4c71-a09b-5558ff11649f",
   "metadata": {},
   "source": [
    "LangChain 中提供了带有历史记录的链路组件，可以通过 LLM 对历史记录进行压缩来支持历史记录"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "3d3f34f6-26c5-4dff-b01e-9ed202e27d7e",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_core.prompts import ChatPromptTemplate\n",
    "\n",
    "# 问答链的系统prompt\n",
    "system_prompt = (\n",
    "    \"你是一个问答任务的助手。 \"\n",
    "    \"请使用检索到的上下文片段回答这个问题。 \"\n",
    "    \"如果你不知道答案就说不知道。 \"\n",
    "    \"请使用简洁的话语回答用户。\"\n",
    "    \"\\n\\n\"\n",
    "    \"{context}\"\n",
    ")\n",
    "# 制定prompt template\n",
    "qa_prompt = ChatPromptTemplate(\n",
    "    [\n",
    "        (\"system\", system_prompt),\n",
    "        (\"placeholder\", \"{chat_history}\"),\n",
    "        (\"human\", \"{input}\"),\n",
    "    ]\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "47e7ac1e-7050-4959-b8b2-7a1024b778b0",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_core.runnables import RunnableBranch\n",
    "\n",
    "# 压缩问题的系统 prompt\n",
    "condense_question_system_template = (\n",
    "    \"请根据聊天记录完善用户最新的问题，\"\n",
    "    \"如果用户最新的问题不需要完善则返回用户的问题。\"\n",
    "    )\n",
    "# 构造压缩问题的 prompt template\n",
    "condense_question_prompt = ChatPromptTemplate([\n",
    "        (\"system\", condense_question_system_template),\n",
    "        (\"placeholder\", \"{chat_history}\"),\n",
    "        (\"human\", \"{input}\"),\n",
    "    ])\n",
    "# 构造检索文档的链\n",
    "# RunnableBranch 会根据条件选择要运行的分支\n",
    "retrieve_docs = RunnableBranch(\n",
    "    # 分支 1: 若聊天记录中没有 chat_history 则直接使用用户问题查询向量数据库\n",
    "    (lambda x: not x.get(\"chat_history\", False), (lambda x: x[\"input\"]) | retriever, ),\n",
    "    # 分支 2 : 若聊天记录中有 chat_history 则先让 llm 根据聊天记录完善问题再查询向量数据库\n",
    "    condense_question_prompt | llm | StrOutputParser() | retriever,\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ed854487-ec88-488b-aee2-fa23fbd2b3cf",
   "metadata": {},
   "source": [
    "这里我们使用之前定义的问答模板即qa_prompt构造问答链，另外我们通过RunnablePassthrough.assign将中间的查询结果存为\"context\"，将最终结果存为\"answer\"。因为查询结果被存为\"context\"，所以我们整合查询结果的函数combine_docs也要做相应的改动。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "69f3261f-a32a-4e4a-9d13-d38f2877a999",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 重新定义 combine_docs\n",
    "def combine_docs(docs):\n",
    "    return \"\\n\\n\".join(doc.page_content for doc in docs[\"context\"]) # 将 docs 改为 docs[\"context\"]\n",
    "# 定义问答链\n",
    "qa_chain = (\n",
    "    RunnablePassthrough.assign(context=combine_docs) # 使用 combine_docs 函数整合 qa_prompt 中的 context\n",
    "    | qa_prompt # 问答模板\n",
    "    | llm\n",
    "    | StrOutputParser() # 规定输出的格式为 str\n",
    ")\n",
    "# 定义带有历史记录的问答链\n",
    "qa_history_chain = RunnablePassthrough.assign(\n",
    "    context = (lambda x: x) | retrieve_docs # 将查询结果存为 content\n",
    "    ).assign(answer=qa_chain) # 将最终结果存为 answer"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "d5c820b3-702b-4004-b6cb-791906d677fd",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'input': '西瓜书是什么？',\n",
       " 'chat_history': [],\n",
       " 'context': [Document(metadata={'author': '', 'creationDate': \"D:20231117152045-00'00'\", 'creator': 'LaTeX with hyperref', 'file_path': 'data/base_data/pdf/pumpkin_book.pdf', 'format': 'PDF 1.5', 'keywords': '', 'modDate': '', 'page': 1, 'producer': 'xdvipdfmx (20200315)', 'source': 'data/base_data/pdf/pumpkin_book.pdf', 'subject': '', 'title': '', 'total_pages': 196, 'trapped': ''}, page_content='前言\\n“周志华老师的《机器学习》（西瓜书）是机器学习领域的经典入门教材之一，周老师为了使尽可能多的读\\n者通过西瓜书对机器学习有所了解, 所以在书中对部分公式的推导细节没有详述，但是这对那些想深究公式推\\n导细节的读者来说可能“不太友好”，本书旨在对西瓜书里比较难理解的公式加以解析，以及对部分公式补充\\n具体的推导细节。”\\n读到这里，大家可能会疑问为啥前面这段话加了引号，因为这只是我们最初的遐想，后来我们了解到，周\\n老师之所以省去这些推导细节的真实原因是，他本尊认为“理工科数学基础扎实点的大二下学生应该对西瓜书\\n中的推导细节无困难吧，要点在书里都有了，略去的细节应能脑补或做练习”。所以...... 本南瓜书只能算是我\\n等数学渣渣在自学的时候记下来的笔记，希望能够帮助大家都成为一名合格的“理工科数学基础扎实点的大二\\n下学生”。\\n使用说明\\n• 南瓜书的所有内容都是以西瓜书的内容为前置知识进行表述的，所以南瓜书的最佳使用方法是以西瓜书\\n为主线，遇到自己推导不出来或者看不懂的公式时再来查阅南瓜书；\\n• 对于初学机器学习的小白，西瓜书第1 章和第2 章的公式强烈不建议深究，简单过一下即可，等你学得'),\n",
       "  Document(metadata={'author': '', 'creationDate': \"D:20231117152045-00'00'\", 'creator': 'LaTeX with hyperref', 'file_path': 'data/base_data/pdf/pumpkin_book.pdf', 'format': 'PDF 1.5', 'keywords': '', 'modDate': '', 'page': 102, 'producer': 'xdvipdfmx (20200315)', 'source': 'data/base_data/pdf/pumpkin_book.pdf', 'subject': '', 'title': '', 'total_pages': 196, 'trapped': ''}, page_content='→_→\\n欢迎去各大电商平台选购纸质版南瓜书《机器学习公式详解第2 版》\\n←_←\\n至于说“西瓜书”图8.9 中伪代码第1 行到第3 行使用的数据集与第5 行到第10 行使用的数据集之\\n间的关系，在“西瓜书”图8.9 下方的一段话有详细的讨论，不再赘述。\\n8.5\\n多样性\\n8.5.1\\n式(8.27) 的解释\\nA (hi|x) = (hi(x) −H(x))2\\n该式表示个体学习器结果与预测结果的差值的平方，即为个体学习器的“分歧”。\\n8.5.2\\n式(8.28) 的解释\\n¯A(h|x) =\\nT\\nX\\ni=1\\nwiA (hi|x)\\n=\\nT\\nX\\ni=1\\nwi (hi(x) −H(x))2\\n该式表示对各个个体学习器的“分歧”加权平均的结果，即集成的“分歧”。\\n8.5.3\\n式(8.29) 的解释\\nE (hi|x) = (f(x) −hi(x))2\\n该式表示个体学习器与真实值之间差值的平方，即个体学习器的平方误差。\\n8.5.4\\n式(8.30) 的解释\\nE(H|x) = (f(x) −H(x))2\\n该式表示集成与真实值之间差值的平方，即集成的平方误差。\\n8.5.5\\n式(8.31) 的推导\\n由(8.28) 知'),\n",
       "  Document(metadata={'author': '', 'creationDate': \"D:20231117152045-00'00'\", 'creator': 'LaTeX with hyperref', 'file_path': 'data/base_data/pdf/pumpkin_book.pdf', 'format': 'PDF 1.5', 'keywords': '', 'modDate': '', 'page': 1, 'producer': 'xdvipdfmx (20200315)', 'source': 'data/base_data/pdf/pumpkin_book.pdf', 'subject': '', 'title': '', 'total_pages': 196, 'trapped': ''}, page_content='• 对于初学机器学习的小白，西瓜书第1 章和第2 章的公式强烈不建议深究，简单过一下即可，等你学得\\n有点飘的时候再回来啃都来得及；\\n• 每个公式的解析和推导我们都力(zhi) 争(neng) 以本科数学基础的视角进行讲解，所以超纲的数学知识\\n我们通常都会以附录和参考文献的形式给出，感兴趣的同学可以继续沿着我们给的资料进行深入学习；\\n• 若南瓜书里没有你想要查阅的公式，或者你发现南瓜书哪个地方有错误，请毫不犹豫地去我们GitHub 的\\nIssues（地址：https://github.com/datawhalechina/pumpkin-book/issues）进行反馈，在对应版块\\n提交你希望补充的公式编号或者勘误信息，我们通常会在24 小时以内给您回复，超过24 小时未回复的\\n话可以微信联系我们（微信号：at-Sm1les）；\\n配套视频教程：https://www.bilibili.com/video/BV1Mh411e7VU\\n在线阅读地址：https://datawhalechina.github.io/pumpkin-book（仅供第1 版）'),\n",
       "  Document(metadata={'author': '', 'creationDate': \"D:20231117152045-00'00'\", 'creator': 'LaTeX with hyperref', 'file_path': 'data/base_data/pdf/pumpkin_book.pdf', 'format': 'PDF 1.5', 'keywords': '', 'modDate': '', 'page': 119, 'producer': 'xdvipdfmx (20200315)', 'source': 'data/base_data/pdf/pumpkin_book.pdf', 'subject': '', 'title': '', 'total_pages': 196, 'trapped': ''}, page_content='←_←')],\n",
       " 'answer': '<think>\\n嗯，用户问“西瓜书是什么？”。首先，我记得西瓜书是周志华老师写的《机器学习》教材，因为书的封面有西瓜，所以大家叫它西瓜书。这本书挺有名的，适合机器学习入门。\\n\\n用户可能刚接触机器学习，或者听说过这本书，想了解更多信息。考虑到用户提到的内容，看起来他们可能在学习南瓜书，也就是西瓜书的公式解析版本。所以用户的问题可能是在确认西瓜书的背景和用途。\\n\\n我应该简明扼要地介绍西瓜书的基本情况，包括作者、内容、适用人群，以及它在机器学习学习中的地位。同时，提到南瓜书作为补充材料，帮助理解公式推导，这样用户能更好地利用这些资源。\\n\\n最后，确保回答准确，避免误解，比如说明西瓜书是教材，南瓜书是它的补充，这样用户不会混淆两者。\\n</think>\\n\\n西瓜书指的是周志华老师所著的《机器学习》教材，因其封面图案是一只西瓜而得名。这本书是机器学习领域的经典入门教材之一，内容涵盖机器学习的基本概念、主要算法和理论基础，适合理工科背景的学生和机器学习初学者学习使用。'}"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 测试一下\n",
    "\n",
    "# 不带聊天记录\n",
    "qa_history_chain.invoke({\n",
    "    \"input\": \"西瓜书是什么？\",\n",
    "    \"chat_history\": []\n",
    "})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "31696c77-c61f-4b95-bae4-efefa846ce12",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'input': '南瓜书跟它有什么关系？',\n",
       " 'chat_history': [('human', '西瓜书是什么？'),\n",
       "  ('ai', '西瓜书是指周志华老师的《机器学习》一书，是机器学习领域的经典入门教材之一。')],\n",
       " 'context': [Document(metadata={'author': '', 'creationDate': \"D:20231117152045-00'00'\", 'creator': 'LaTeX with hyperref', 'file_path': 'data/base_data/pdf/pumpkin_book.pdf', 'format': 'PDF 1.5', 'keywords': '', 'modDate': '', 'page': 1, 'producer': 'xdvipdfmx (20200315)', 'source': 'data/base_data/pdf/pumpkin_book.pdf', 'subject': '', 'title': '', 'total_pages': 196, 'trapped': ''}, page_content='前言\\n“周志华老师的《机器学习》（西瓜书）是机器学习领域的经典入门教材之一，周老师为了使尽可能多的读\\n者通过西瓜书对机器学习有所了解, 所以在书中对部分公式的推导细节没有详述，但是这对那些想深究公式推\\n导细节的读者来说可能“不太友好”，本书旨在对西瓜书里比较难理解的公式加以解析，以及对部分公式补充\\n具体的推导细节。”\\n读到这里，大家可能会疑问为啥前面这段话加了引号，因为这只是我们最初的遐想，后来我们了解到，周\\n老师之所以省去这些推导细节的真实原因是，他本尊认为“理工科数学基础扎实点的大二下学生应该对西瓜书\\n中的推导细节无困难吧，要点在书里都有了，略去的细节应能脑补或做练习”。所以...... 本南瓜书只能算是我\\n等数学渣渣在自学的时候记下来的笔记，希望能够帮助大家都成为一名合格的“理工科数学基础扎实点的大二\\n下学生”。\\n使用说明\\n• 南瓜书的所有内容都是以西瓜书的内容为前置知识进行表述的，所以南瓜书的最佳使用方法是以西瓜书\\n为主线，遇到自己推导不出来或者看不懂的公式时再来查阅南瓜书；\\n• 对于初学机器学习的小白，西瓜书第1 章和第2 章的公式强烈不建议深究，简单过一下即可，等你学得'),\n",
       "  Document(metadata={'author': '', 'creationDate': \"D:20231117152045-00'00'\", 'creator': 'LaTeX with hyperref', 'file_path': 'data/base_data/pdf/pumpkin_book.pdf', 'format': 'PDF 1.5', 'keywords': '', 'modDate': '', 'page': 13, 'producer': 'xdvipdfmx (20200315)', 'source': 'data/base_data/pdf/pumpkin_book.pdf', 'subject': '', 'title': '', 'total_pages': 196, 'trapped': ''}, page_content='→_→\\n欢迎去各大电商平台选购纸质版南瓜书《机器学习公式详解第2 版》\\n←_←\\n第1 章\\n绪论\\n本章作为“西瓜书”的开篇，主要讲解什么是机器学习以及机器学习的相关数学符号，为后续内容作\\n铺垫，并未涉及复杂的算法理论，因此阅读本章时只需耐心梳理清楚所有概念和数学符号即可。此外，在\\n阅读本章前建议先阅读西瓜书目录前页的《主要符号表》，它能解答在阅读“西瓜书”过程中产生的大部\\n分对数学符号的疑惑。\\n本章也作为本书的开篇，笔者在此赘述一下本书的撰写初衷，本书旨在以“过来人”的视角陪读者一\\n起阅读“西瓜书”，尽力帮读者消除阅读过程中的“数学恐惧”，只要读者学习过《高等数学》、《线性代\\n数》和《概率论与数理统计》这三门大学必修的数学课，均能看懂本书对西瓜书中的公式所做的解释和推\\n导，同时也能体会到这三门数学课在机器学习上碰撞产生的“数学之美”。\\n1.1\\n引言\\n本节以概念理解为主，在此对“算法”和“模型”作补充说明。“算法”是指从数据中学得“模型”的具\\n体方法，例如后续章节中将会讲述的线性回归、对数几率回归、决策树等。“算法”产出的结果称为“模型”，'),\n",
       "  Document(metadata={'author': '', 'creationDate': \"D:20231117152045-00'00'\", 'creator': 'LaTeX with hyperref', 'file_path': 'data/base_data/pdf/pumpkin_book.pdf', 'format': 'PDF 1.5', 'keywords': '', 'modDate': '', 'page': 87, 'producer': 'xdvipdfmx (20200315)', 'source': 'data/base_data/pdf/pumpkin_book.pdf', 'subject': '', 'title': '', 'total_pages': 196, 'trapped': ''}, page_content='→_→\\n欢迎去各大电商平台选购纸质版南瓜书《机器学习公式详解第2 版》\\n←_←\\n[2] 李航. 统计学习方法. 清华大学出版社, 2012.\\n→_→\\n配套视频教程：https://www.bilibili.com/video/BV1Mh411e7VU\\n←_←'),\n",
       "  Document(metadata={'author': '', 'creationDate': \"D:20231117152045-00'00'\", 'creator': 'LaTeX with hyperref', 'file_path': 'data/base_data/pdf/pumpkin_book.pdf', 'format': 'PDF 1.5', 'keywords': '', 'modDate': '', 'page': 1, 'producer': 'xdvipdfmx (20200315)', 'source': 'data/base_data/pdf/pumpkin_book.pdf', 'subject': '', 'title': '', 'total_pages': 196, 'trapped': ''}, page_content='• 对于初学机器学习的小白，西瓜书第1 章和第2 章的公式强烈不建议深究，简单过一下即可，等你学得\\n有点飘的时候再回来啃都来得及；\\n• 每个公式的解析和推导我们都力(zhi) 争(neng) 以本科数学基础的视角进行讲解，所以超纲的数学知识\\n我们通常都会以附录和参考文献的形式给出，感兴趣的同学可以继续沿着我们给的资料进行深入学习；\\n• 若南瓜书里没有你想要查阅的公式，或者你发现南瓜书哪个地方有错误，请毫不犹豫地去我们GitHub 的\\nIssues（地址：https://github.com/datawhalechina/pumpkin-book/issues）进行反馈，在对应版块\\n提交你希望补充的公式编号或者勘误信息，我们通常会在24 小时以内给您回复，超过24 小时未回复的\\n话可以微信联系我们（微信号：at-Sm1les）；\\n配套视频教程：https://www.bilibili.com/video/BV1Mh411e7VU\\n在线阅读地址：https://datawhalechina.github.io/pumpkin-book（仅供第1 版）')],\n",
       " 'answer': '<think>\\n好的，我现在需要回答用户的问题：“南瓜书跟西瓜书有什么关系？”首先，我得理解这两个术语分别指的是什么。\\n\\n根据提供的上下文，西瓜书指的是周志华老师的《机器学习》教材，而南瓜书是另一本辅助学习的书籍。南瓜书的作者提到，他们最初以为西瓜书省略了一些公式推导细节，所以写南瓜书来解析这些细节。但后来他们了解到，周老师认为这些细节对数学基础扎实的学生来说并不困难，所以南瓜书实际上是作为补充笔记存在的。\\n\\n南瓜书的使用说明指出，它以西瓜书为前置知识，读者在遇到难以理解的公式时可以查阅南瓜书。此外，南瓜书还为机器学习初学者提供了学习建议，比如不建议过早深入研究前两章的公式，等有一定基础后再回过头来学习。\\n\\n所以，南瓜书和西瓜书的关系可以总结为：南瓜书是基于西瓜书内容的补充和解析，帮助读者更好地理解和掌握西瓜书中的公式和推导细节。南瓜书的读者应该先阅读西瓜书，遇到困难时再参考南瓜书，这样学习效果会更好。\\n\\n在回答用户问题时，我需要简明扼要地说明这一点，同时可能提到南瓜书的作者是谁，以及它的编写初衷。这样用户就能清楚地理解南瓜书和西瓜书之间的关系，以及南瓜书如何辅助学习西瓜书的内容。\\n</think>\\n\\n南瓜书与西瓜书有着密切的关系。南瓜书是基于周志华老师的《机器学习》（西瓜书）编写的一本辅助学习资料，旨在解析西瓜书中较为复杂的公式和推导细节，帮助读者更好地理解和掌握西瓜书中的内容。因此，南瓜书可以视为学习西瓜书的补充和延伸，两者相辅相成，共同助力读者深入理解机器学习的相关知识和公式推导。'}"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 带聊天记录\n",
    "qa_history_chain.invoke({\n",
    "    \"input\": \"南瓜书跟它有什么关系？\",\n",
    "    \"chat_history\": [\n",
    "        (\"human\", \"西瓜书是什么？\"),\n",
    "        (\"ai\", \"西瓜书是指周志华老师的《机器学习》一书，是机器学习领域的经典入门教材之一。\"),\n",
    "    ]\n",
    "})"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fca9208b-951a-4dac-b442-fb59ab258779",
   "metadata": {},
   "source": [
    "7. 部署前端界面"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "c98b2e12-8efb-43d3-9e61-9cf15cf66cb4",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "huggingface/tokenizers: The current process just got forked, after parallelism has already been used. Disabling parallelism to avoid deadlocks...\n",
      "To disable this warning, you can either:\n",
      "\t- Avoid using `tokenizers` before the fork if possible\n",
      "\t- Explicitly set the environment variable TOKENIZERS_PARALLELISM=(true | false)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple\n",
      "Collecting streamlit\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/46/9e/e51e34f504940da00145795b9e8be9c129704708b071f672f3626a37d842/streamlit-1.44.0-py3-none-any.whl (9.8 MB)\n",
      "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m9.8/9.8 MB\u001b[0m \u001b[31m5.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0ma \u001b[36m0:00:01\u001b[0m\n",
      "\u001b[?25hCollecting altair<6,>=4.0 (from streamlit)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/aa/f3/0b6ced594e51cc95d8c1fc1640d3623770d01e4969d29c0bd09945fafefa/altair-5.5.0-py3-none-any.whl (731 kB)\n",
      "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m731.2/731.2 kB\u001b[0m \u001b[31m3.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0ma \u001b[36m0:00:01\u001b[0m\n",
      "\u001b[?25hCollecting blinker<2,>=1.0.0 (from streamlit)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl (8.5 kB)\n",
      "Requirement already satisfied: cachetools<6,>=4.0 in /opt/conda/lib/python3.11/site-packages (from streamlit) (5.5.2)\n",
      "Requirement already satisfied: click<9,>=7.0 in /opt/conda/lib/python3.11/site-packages (from streamlit) (8.1.7)\n",
      "Requirement already satisfied: numpy<3,>=1.23 in /opt/conda/lib/python3.11/site-packages (from streamlit) (1.24.3)\n",
      "Requirement already satisfied: packaging<25,>=20 in /opt/conda/lib/python3.11/site-packages (from streamlit) (24.1)\n",
      "Requirement already satisfied: pandas<3,>=1.4.0 in /opt/conda/lib/python3.11/site-packages (from streamlit) (2.2.3)\n",
      "Requirement already satisfied: pillow<12,>=7.1.0 in /opt/conda/lib/python3.11/site-packages (from streamlit) (10.4.0)\n",
      "Requirement already satisfied: protobuf<6,>=3.20 in /opt/conda/lib/python3.11/site-packages (from streamlit) (5.28.2)\n",
      "Requirement already satisfied: pyarrow>=7.0 in /opt/conda/lib/python3.11/site-packages (from streamlit) (17.0.0)\n",
      "Requirement already satisfied: requests<3,>=2.27 in /opt/conda/lib/python3.11/site-packages (from streamlit) (2.32.3)\n",
      "Requirement already satisfied: tenacity<10,>=8.1.0 in /opt/conda/lib/python3.11/site-packages (from streamlit) (8.5.0)\n",
      "Collecting toml<2,>=0.10.1 (from streamlit)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/44/6f/7120676b6d73228c96e17f1f794d8ab046fc910d781c8d151120c3f1569e/toml-0.10.2-py2.py3-none-any.whl (16 kB)\n",
      "Requirement already satisfied: typing-extensions<5,>=4.4.0 in /opt/conda/lib/python3.11/site-packages (from streamlit) (4.12.2)\n",
      "Collecting watchdog<7,>=2.1.5 (from streamlit)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/b5/e8/dbf020b4d98251a9860752a094d09a65e1b436ad181faf929983f697048f/watchdog-6.0.0-py3-none-manylinux2014_x86_64.whl (79 kB)\n",
      "Collecting gitpython!=3.1.19,<4,>=3.0.7 (from streamlit)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/1d/9a/4114a9057db2f1462d5c8f8390ab7383925fe1ac012eaa42402ad65c2963/GitPython-3.1.44-py3-none-any.whl (207 kB)\n",
      "Collecting pydeck<1,>=0.8.0b4 (from streamlit)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/ab/4c/b888e6cf58bd9db9c93f40d1c6be8283ff49d88919231afe93a6bcf61626/pydeck-0.9.1-py2.py3-none-any.whl (6.9 MB)\n",
      "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m6.9/6.9 MB\u001b[0m \u001b[31m2.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m00:01\u001b[0m00:01\u001b[0m\n",
      "\u001b[?25hRequirement already satisfied: tornado<7,>=6.0.3 in /opt/conda/lib/python3.11/site-packages (from streamlit) (6.4.1)\n",
      "Requirement already satisfied: jinja2 in /opt/conda/lib/python3.11/site-packages (from altair<6,>=4.0->streamlit) (3.1.4)\n",
      "Requirement already satisfied: jsonschema>=3.0 in /opt/conda/lib/python3.11/site-packages (from altair<6,>=4.0->streamlit) (4.23.0)\n",
      "Collecting narwhals>=1.14.2 (from altair<6,>=4.0->streamlit)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/e9/96/79a6168dc7a5098066e097c01a45d01608c8df6552dfb92a2676ce623186/narwhals-1.32.0-py3-none-any.whl (320 kB)\n",
      "Collecting gitdb<5,>=4.0.1 (from gitpython!=3.1.19,<4,>=3.0.7->streamlit)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/a0/61/5c78b91c3143ed5c14207f463aecfc8f9dbb5092fb2869baf37c273b2705/gitdb-4.0.12-py3-none-any.whl (62 kB)\n",
      "Requirement already satisfied: python-dateutil>=2.8.2 in /opt/conda/lib/python3.11/site-packages (from pandas<3,>=1.4.0->streamlit) (2.9.0.post0)\n",
      "Requirement already satisfied: pytz>=2020.1 in /opt/conda/lib/python3.11/site-packages (from pandas<3,>=1.4.0->streamlit) (2024.2)\n",
      "Requirement already satisfied: tzdata>=2022.7 in /opt/conda/lib/python3.11/site-packages (from pandas<3,>=1.4.0->streamlit) (2024.2)\n",
      "Requirement already satisfied: charset-normalizer<4,>=2 in /opt/conda/lib/python3.11/site-packages (from requests<3,>=2.27->streamlit) (3.3.2)\n",
      "Requirement already satisfied: idna<4,>=2.5 in /opt/conda/lib/python3.11/site-packages (from requests<3,>=2.27->streamlit) (3.7)\n",
      "Requirement already satisfied: urllib3<3,>=1.21.1 in /opt/conda/lib/python3.11/site-packages (from requests<3,>=2.27->streamlit) (2.2.2)\n",
      "Requirement already satisfied: certifi>=2017.4.17 in /opt/conda/lib/python3.11/site-packages (from requests<3,>=2.27->streamlit) (2024.8.30)\n",
      "Collecting smmap<6,>=3.0.1 (from gitdb<5,>=4.0.1->gitpython!=3.1.19,<4,>=3.0.7->streamlit)\n",
      "  Downloading https://pypi.tuna.tsinghua.edu.cn/packages/04/be/d09147ad1ec7934636ad912901c5fd7667e1c858e19d355237db0d0cd5e4/smmap-5.0.2-py3-none-any.whl (24 kB)\n",
      "Requirement already satisfied: MarkupSafe>=2.0 in /opt/conda/lib/python3.11/site-packages (from jinja2->altair<6,>=4.0->streamlit) (3.0.1)\n",
      "Requirement already satisfied: attrs>=22.2.0 in /opt/conda/lib/python3.11/site-packages (from jsonschema>=3.0->altair<6,>=4.0->streamlit) (24.2.0)\n",
      "Requirement already satisfied: jsonschema-specifications>=2023.03.6 in /opt/conda/lib/python3.11/site-packages (from jsonschema>=3.0->altair<6,>=4.0->streamlit) (2024.10.1)\n",
      "Requirement already satisfied: referencing>=0.28.4 in /opt/conda/lib/python3.11/site-packages (from jsonschema>=3.0->altair<6,>=4.0->streamlit) (0.35.1)\n",
      "Requirement already satisfied: rpds-py>=0.7.1 in /opt/conda/lib/python3.11/site-packages (from jsonschema>=3.0->altair<6,>=4.0->streamlit) (0.20.0)\n",
      "Requirement already satisfied: six>=1.5 in /opt/conda/lib/python3.11/site-packages (from python-dateutil>=2.8.2->pandas<3,>=1.4.0->streamlit) (1.16.0)\n",
      "Installing collected packages: watchdog, toml, smmap, narwhals, blinker, pydeck, gitdb, gitpython, altair, streamlit\n",
      "Successfully installed altair-5.5.0 blinker-1.9.0 gitdb-4.0.12 gitpython-3.1.44 narwhals-1.32.0 pydeck-0.9.1 smmap-5.0.2 streamlit-1.44.0 toml-0.10.2 watchdog-6.0.0\n",
      "\u001b[33mWARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager, possibly rendering your system unusable.It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv. Use the --root-user-action option if you know what you are doing and want to suppress this warning.\u001b[0m\u001b[33m\n",
      "\u001b[0m"
     ]
    }
   ],
   "source": [
    "!pip install streamlit"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "5d581bdb-386b-441d-a39e-a6c6cc3e5e48",
   "metadata": {},
   "outputs": [],
   "source": [
    "import streamlit as st\n",
    "from langchain_openai import ChatOpenAI\n",
    "import os\n",
    "from langchain_core.output_parsers import StrOutputParser\n",
    "from langchain_core.prompts import ChatPromptTemplate\n",
    "from langchain_core.runnables import RunnableBranch, RunnablePassthrough\n",
    "from langchain_community.vectorstores import Chroma"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "40cd7583-b6ce-41d9-bfbc-d251ffad8a98",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 1. 定义 get_retriever 函数，该函数返回一个检索器\n",
    "def get_retriever():\n",
    "    # 定义 Embeddings\n",
    "    embedding = Embeddings()\n",
    "    # 向量数据库持久化路径\n",
    "    persist_directory = 'data/chroma'\n",
    "    # 加载数据库\n",
    "    vectordb = Chroma(\n",
    "        persist_directory=persist_directory,\n",
    "        embedding_function=embedding\n",
    "    )\n",
    "    return vectordb.as_retriever()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "1a99b1b9-ea9f-419f-89b4-d0be8ed60f6d",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 2. 定义combine_docs函数， 该函数处理检索器返回的文本\n",
    "def combine_docs(docs):\n",
    "    return \"\\n\\n\".join(doc.page_content for doc in docs[\"context\"])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "c7055356-dd9d-46a7-847d-d08a95f8b59d",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 3. 定义get_qa_history_chain函数，该函数可以返回一个检索问答链\n",
    "def get_qa_history_chain():\n",
    "    retriever = get_retriever()\n",
    "    llm = llm = DeepSeekLLM(api_key = DEEPSEEK_API_KEY)\n",
    "    condense_question_system_template = (\n",
    "        \"请根据聊天记录总结用户最近的问题，\"\n",
    "        \"如果没有多余的聊天记录则返回用户的问题。\"\n",
    "    )\n",
    "    condense_question_prompt = ChatPromptTemplate([\n",
    "            (\"system\", condense_question_system_template),\n",
    "            (\"placeholder\", \"{chat_history}\"),\n",
    "            (\"human\", \"{input}\"),\n",
    "        ])\n",
    "\n",
    "    retrieve_docs = RunnableBranch(\n",
    "        (lambda x: not x.get(\"chat_history\", False), (lambda x: x[\"input\"]) | retriever, ),\n",
    "        condense_question_prompt | llm | StrOutputParser() | retriever,\n",
    "    )\n",
    "\n",
    "    system_prompt = (\n",
    "        \"你是一个问答任务的助手。 \"\n",
    "        \"请使用检索到的上下文片段回答这个问题。 \"\n",
    "        \"如果你不知道答案就说不知道。 \"\n",
    "        \"请使用简洁的话语回答用户。\"\n",
    "        \"\\n\\n\"\n",
    "        \"{context}\"\n",
    "    )\n",
    "    qa_prompt = ChatPromptTemplate.from_messages(\n",
    "        [\n",
    "            (\"system\", system_prompt),\n",
    "            (\"placeholder\", \"{chat_history}\"),\n",
    "            (\"human\", \"{input}\"),\n",
    "        ]\n",
    "    )\n",
    "    qa_chain = (\n",
    "        RunnablePassthrough().assign(context=combine_docs)\n",
    "        | qa_prompt\n",
    "        | llm\n",
    "        | StrOutputParser()\n",
    "    )\n",
    "\n",
    "    qa_history_chain = RunnablePassthrough().assign(\n",
    "        context = retrieve_docs, \n",
    "        ).assign(answer=qa_chain)\n",
    "    return qa_history_chain"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "ec52e754-1cf2-499a-a082-50eff9fab394",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 4. 定义gen_response函数，它接受检索问答链、用户输入及聊天历史，并以流式返回该链输出\n",
    "def gen_response(chain, input, chat_history):\n",
    "    response = chain.stream({\n",
    "        \"input\": input,\n",
    "        \"chat_history\": chat_history\n",
    "    })\n",
    "    for res in response:\n",
    "        if \"answer\" in res.keys():\n",
    "            yield res[\"answer\"]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "14d9b600-4bd6-42b5-8181-3966cdca2b0b",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 5. 定义main函数，该函数制定显示效果与逻辑\n",
    "def main():\n",
    "    st.markdown('### 🦜🔗 基于 DeepSeek R1 搭建 RAG 应用')\n",
    "    # st.session_state可以存储用户与应用交互期间的状态与数据\n",
    "    # 存储对话历史\n",
    "    if \"messages\" not in st.session_state:\n",
    "        st.session_state.messages = []\n",
    "    # 存储检索问答链\n",
    "    if \"qa_history_chain\" not in st.session_state:\n",
    "        st.session_state.qa_history_chain = get_qa_history_chain()\n",
    "    # 建立容器 高度为500 px\n",
    "    messages = st.container(height=550)\n",
    "    # 显示整个对话历史\n",
    "    for message in st.session_state.messages: # 遍历对话历史\n",
    "            with messages.chat_message(message[0]): # messages指在容器下显示，chat_message显示用户及ai头像\n",
    "                st.write(message[1]) # 打印内容\n",
    "    if prompt := st.chat_input(\"Say something\"):\n",
    "        # 将用户输入添加到对话历史中\n",
    "        st.session_state.messages.append((\"human\", prompt))\n",
    "        # 显示当前用户输入\n",
    "        with messages.chat_message(\"human\"):\n",
    "            st.write(prompt)\n",
    "        # 生成回复\n",
    "        answer = gen_response(\n",
    "            chain=st.session_state.qa_history_chain,\n",
    "            input=prompt,\n",
    "            chat_history=st.session_state.messages\n",
    "        )\n",
    "        # 流式输出\n",
    "        with messages.chat_message(\"ai\"):\n",
    "            output = st.write_stream(answer)\n",
    "        # 将输出存入st.session_state.messages\n",
    "        st.session_state.messages.append((\"ai\", output))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "876c8a04-fe9b-4eb2-9f11-b165fcbb06fd",
   "metadata": {},
   "source": [
    "将上述代码粘贴到一个 Python 文件，再通过 “streamlit run”运行即可"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
